Scrapy爬取遭目标网站封禁问题求助(Scrapy1.5/Python3.5)
解决Scrapy爬取时的403封禁与爬取量受限问题
看起来你已经做了不少基础的反爬规避工作,但网站的反爬机制还是在限制你的爬取。结合你的场景(Scrapy 1.5 + Python 3.5),我给你几个针对性的优化方案:
1. 轮换多样化的User-Agent,避免单一标识
单一的User-Agent很容易被识别,建议使用一批真实的浏览器UA并随机切换。你可以手动实现中间件,适配Scrapy 1.5版本:
自定义User-Agent中间件
在项目的middlewares.py中添加:
import random from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware class RotateUserAgentMiddleware(UserAgentMiddleware): def __init__(self, user_agent=''): self.user_agent = user_agent # 收集一批真实的浏览器UA,可自行补充更多 self.user_agents = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' ] def process_request(self, request, spider): ua = random.choice(self.user_agents) if ua: request.headers.setdefault('User-Agent', ua)
然后在settings.py中启用这个中间件,禁用默认UA中间件:
DOWNLOADER_MIDDLEWARES = { 'your_project_name.middlewares.RotateUserAgentMiddleware': 400, 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, }
2. 优化TOR的IP轮换策略
仅使用TOR可能IP更换不及时,导致同一个IP请求过多被封禁。可以通过控制TOR控制器主动切换IP:
步骤1:开启TOR控制端口
修改TOR的配置文件(如torrc),添加:
ControlPort 9051 HashedControlPassword 你的加密密码(可通过`tor --hash-password 你的明文密码`生成)
步骤2:编写TOR IP轮换中间件
在middlewares.py中添加:
from stem import Signal from stem.control import Controller import scrapy class TorIPRotateMiddleware(object): def __init__(self): self.controller = Controller.from_port(port=9051) self.controller.authenticate(password='你的TOR控制密码') def process_request(self, request, spider): # 每10次请求更换一次IP,可根据实际情况调整频率 if spider.crawler.stats.get_value('downloader/request_count', 0) % 10 == 0: self.controller.signal(Signal.NEWNYM) spider.logger.info("TOR IP已更换") # 确保请求通过TOR代理 request.meta['proxy'] = 'http://127.0.0.1:9050'
在settings.py中启用该中间件:
DOWNLOADER_MIDDLEWARES.update({ 'your_project_name.middlewares.TorIPRotateMiddleware': 500, })
3. 调整请求间隔与并发数,模拟真实用户行为
固定的下载延迟容易被识别,建议开启随机延迟并降低并发数:
DOWNLOAD_DELAY = 3 # 基础延迟3秒 RANDOMIZE_DOWNLOAD_DELAY = True # 随机延迟范围为基础延迟的0.8-1.2倍(2.4-3.6秒) CONCURRENT_REQUESTS = 1 # 并发数设为1,避免同时发送多个请求 CONCURRENT_REQUESTS_PER_DOMAIN = 1 # 每个域名同时请求数设为1
4. 补充完整请求头,模拟浏览器请求
除了User-Agent,添加浏览器常用的请求头,在settings.py中设置:
DEFAULT_REQUEST_HEADERS = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate, br', 'DNT': '1', # 开启"不跟踪"请求标识 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' }
5. 配置重试机制,针对封禁状态码重试
让Scrapy自动重试403等封禁状态码,重试时会自动触发UA和IP轮换:
RETRY_ENABLED = True RETRY_TIMES = 3 # 最多重试3次 RETRY_HTTP_CODES = [403, 500, 502, 503, 504] # 需要重试的状态码列表
6. 打乱请求顺序,避免规律爬取
默认Scrapy是广度优先爬取,容易形成固定请求规律。可以改为深度优先,或者在爬虫中随机打乱待爬链接:
# 在settings.py中设置深度优先爬取 DEPTH_PRIORITY = 1 SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue' SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue'
或者在爬虫的start_requests方法中,随机打乱起始链接列表。
尝试组合这些方案,应该能有效降低被封禁的概率,提升爬取量。
内容的提问来源于stack exchange,提问作者Ashish
相关产品推荐
相关产品推荐

