You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Scrapy爬取DNB网站遭遇403封禁,Selenium/Requests可正常访问的问题咨询

Scrapy爬取DNB页面失败但Selenium/Requests正常的原因与解决办法

我来帮你捋捋为什么会出现这种差异,以及对应的解决思路:

可能的核心原因

1. 请求头的完整性差异

DNB的反爬系统大概率会校验请求头的细节。Scrapy默认的请求头缺少很多浏览器特有的字段(比如Accept-Language、Sec-Fetch-*系列、Referer等),而Requests在默认情况下会自动补充部分贴近浏览器的头,Selenium则完全复刻浏览器的请求头,所以能绕过检测。

2. 代理IP质量或配置问题

你配置的代理列表里的IP可能已经被DNB拉黑,或者scrapy_proxies中间件的配置存在问题(比如PROXY_MODE=0的随机代理逻辑没生效,部分代理本身无法访问目标站点)。另外,重试次数设置为10次,反而可能触发反爬系统的恶意请求判定,加重封锁。

3. Cookie会话逻辑不匹配

浏览器访问时会先加载DNB的首页或搜索页,生成必要的会话Cookie,而Scrapy直接请求详情页,缺少这些关键的会话标识。即使开启了COOKIES_ENABLED,Scrapy的CookieJar也无法模拟浏览器的Cookie生成流程(比如需要通过JS生成的Cookie)。

4. 并发请求触发反爬

你的Scrapy配置中CONCURRENT_REQUESTS_PER_DOMAIN=10,即使有随机延迟,单域名的并发请求量也远高于正常浏览器的访问频率,很容易被反爬系统识别为爬虫。而Selenium和Requests都是单请求模式,不会触发并发限制。

5. 下载中间件的优先级冲突

虽然你配置了UA和代理中间件,但优先级设置可能存在问题,导致UA或代理没有正确应用到请求上。比如RetryMiddleware的优先级是90,可能在代理生效前就重试了请求,导致无效的重试请求暴露了真实IP。


分步解决办法

1. 完全复刻浏览器请求头

在Spider中手动设置和浏览器一致的请求头,或者在settings.py中全局配置:

# 在Spider的parse方法或start_requests中设置
headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.5',
    'Referer': 'https://www.dnb.com/business-directory',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'same-origin',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36'
}
yield scrapy.Request(url=target_url, headers=headers, callback=self.parse)

2. 验证并更换高质量代理

先手动测试代理列表中的IP是否有效:

import requests
proxy = 'http://your-proxy-ip:port'
try:
    response = requests.get(target_url, proxies={'http': proxy, 'https': proxy}, timeout=10)
    print(f"Proxy {proxy} works, status code: {response.status_code}")
except Exception as e:
    print(f"Proxy {proxy} failed: {str(e)}")

如果大部分代理失效,更换为高匿、稳定的代理IP池。同时调整配置:

'RETRY_TIMES': 3,  # 减少重试次数,避免触发反爬
'PROXY_MODE': 1,  # 每个请求更换代理

3. 模拟浏览器的Cookie生成流程

先请求DNB的首页,获取会话Cookie后再请求目标页面:

def start_requests(self):
    # 先访问首页建立会话
    yield scrapy.Request(url='https://www.dnb.com/', callback=self.fetch_target_page)

def fetch_target_page(self, response):
    # 携带首页的Cookie请求目标页面
    yield scrapy.Request(url=target_url, callback=self.parse)

4. 降低并发与调整访问频率

修改settings.py中的并发和延迟配置,贴近正常用户的访问行为:

'DOWNLOAD_DELAY': 2.5,
'CONCURRENT_REQUESTS': 2,
'CONCURRENT_REQUESTS_PER_DOMAIN': 1,
'RANDOMIZE_DOWNLOAD_DELAY': True,

5. 调整下载中间件的优先级

确保中间件的执行顺序正确,比如代理中间件先于UA中间件生效,参考官方文档调整优先级:

'DOWNLOADER_MIDDLEWARES': {
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
    'scrapy_proxies.RandomProxy': 100,
    'scrapy_user_agents.middlewares.RandomUserAgentMiddleware': 200,
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 90,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110,
}

6. 集成Selenium到Scrapy中

如果以上方法都无效,可以使用scrapy-selenium中间件,让Scrapy通过浏览器发送请求,完全模拟你的手动访问流程:

# 安装scrapy-selenium后,在settings中配置
'DOWNLOADER_MIDDLEWARES': {
    'scrapy_selenium.SeleniumMiddleware': 800
},
'SELENIUM_DRIVER_NAME': 'chrome',
'SELENIUM_DRIVER_EXECUTABLE_PATH': '/path/to/chromedriver',
'SELENIUM_DRIVER_ARGUMENTS': ['--headless=new']

内容的提问来源于stack exchange,提问作者Ahmed Ellaban

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:47:46