使用Scrapy中间件处理Indeed爬虫URL时出现无限循环求助
问题分析与解决
无限循环的根本原因
你的中间件判断逻辑太粗糙:仅通过字符串包含检查域名是否存在,但当ScrapeOps代理中间件处理请求后,URL会被替换为代理服务的地址(格式类似http://xxx.proxy.com/https://fr.indeed.com/xxx),此时原域名https://fr.indeed.com不在代理URL中,你的中间件会再次拼接域名,生成https://fr.indeed.comhttp://xxx.proxy.com/https://fr.indeed.com/xxx这类错误URL,进而触发重复处理,陷入无限循环。
此外,字符串包含的判断方式本身就不准确——如果某URL的参数里碰巧包含fr.indeed.com,也会出现误判。
修复后的中间件代码
改用urllib.parse判断URL是否为绝对路径,仅对相对路径进行域名拼接:
from urllib.parse import urlparse class IndeedDomainVerificationMiddleware: def __init__(self, indeed_domain_url): self.indeed_domain_url = indeed_domain_url.rstrip('/') # 移除末尾斜杠,避免重复拼接 @classmethod def from_crawler(cls, crawler): return cls(indeed_domain_url=crawler.settings.get('INDEED_DOMAIN_URL')) def process_request(self, request, spider): if spider.name != 'Indeed': return None parsed_url = urlparse(request.url) # 仅当URL是相对路径(无协议和域名)时才拼接 if not parsed_url.scheme and not parsed_url.netloc: # 兼容开头不带斜杠的相对路径(如"cmd/jobs") if not request.url.startswith('/'): new_url = f"{self.indeed_domain_url}/{request.url}" else: new_url = f"{self.indeed_domain_url}{request.url}" return request.replace(url=new_url) return None
额外优化点
- 在
__init__中给域名移除末尾斜杠,避免生成https://fr.indeed.com//cmd/jobs这类带重复斜杠的无效URL。 - 提前判断爬虫名称,不符合则直接返回,减少不必要的逻辑执行。
为什么改Spider中间件没用?
Spider中间件仅处理爬虫生成的Request和返回的Response,而代理中间件属于下载中间件,请求仍会先经过代理处理导致URL被修改,进而再次触发错误判断。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

