使用Scrapy爬取铁路网站遇403错误及终端冻结,求解决方案
解决Scrapy爬取铁路网站时的403错误与请求冻结问题
一、补全请求头,模拟真实浏览器行为
很多网站的反爬机制会检查请求头完整性,仅设置User-Agent远远不够:
- 打开浏览器开发者工具(F12),访问目标网站后复制完整请求头(包含
Accept、Accept-Language、Referer、Connection等字段)。 - 在Scrapy的
settings.py中添加全局请求头配置:DEFAULT_REQUEST_HEADERS = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'pl-PL,pl;q=0.8,en-US;q=0.5,en;q=0.3', 'Referer': 'https://www.intercity.pl/', # 根据目标网站调整来源地址 'Connection': 'keep-alive', } - 测试时用
scrapy fetch --verbose <目标URL>命令,查看请求头是否与浏览器一致,同时观察响应内容是否包含反爬提示(如验证码、访问受限页面)。
二、恢复Cookie功能,不要盲目禁用
你之前禁用Cookie可能触发了网站的会话验证机制:
- 在
settings.py中设置COOKIES_ENABLED = True(Scrapy默认开启,若之前手动关闭则改回)。 - 部分网站会在首次请求时返回
Set-Cookie,后续请求必须携带这些Cookie才能通过验证,禁用Cookie会直接导致403错误。
三、处理第二个链接的冻结问题:启用JS渲染
rozklad-pkp.pl这类铁路网站大概率依赖JavaScript动态加载内容,Scrapy默认的静态请求会卡住或返回空内容:
- 安装
scrapy-playwright中间件实现JS渲染:- 安装依赖:
pip install scrapy-playwright - 在
settings.py中更新配置:DOWNLOADER_MIDDLEWARES = { 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, 'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 400, 'scrapy_playwright.middleware.PlaywrightMiddleware': 543, } PLAYWRIGHT_LAUNCH_OPTIONS = { 'headless': True, 'args': ['--no-sandbox'], } - 测试时使用命令:
scrapy fetch --render <第二个目标URL>,验证是否能正常获取响应。
- 安装依赖:
四、降低请求频率,避免IP封禁
网站可能因请求频率过高直接拉黑你的IP:
- 在
settings.py中调整限流参数:DOWNLOAD_DELAY = 3 # 延长下载延迟至3秒 CONCURRENT_REQUESTS_PER_DOMAIN = 1 # 每个域名仅允许1个并发请求 - 若调整后仍无效,换用手机热点等其他网络测试。如果换网络后能成功,说明当前IP已被封禁,需要配置代理服务(如使用
scrapy-proxies中间件)。
五、用requests做最小化测试,定位问题根源
先脱离Scrapy,用requests库手动构造请求,验证是否能正常获取响应:
import requests headers = { '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', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'pl-PL,pl;q=0.8,en-US;q=0.5,en;q=0.3', 'Referer': 'https://www.intercity.pl/', } # 测试第一个链接 response1 = requests.get('https://www.intercity.pl/pl/site/dla-pasazera/informacje/frekwencja.html?location=&date=2022-10-25&category%5Beic_premium%5D=eip&category%5Beic%5D=eic&category%5Bic%5D=ic&category%5Btlk%5D=tlk', headers=headers) print(f"第一个链接状态码:{response1.status_code}") print(response1.text[:500]) # 测试第二个链接 response2 = requests.get('https://rozklad-pkp.pl/pl/sq?maxJourneys=40&start=yes&dirInput=&GUIREQProduct_0=on&GUIREQProduct_1=on&GUIREQProduct_2=on&advancedProductMode=&boardType=arr&input=&input=5100028&date=25.10.22&dateStart=25.10.22&REQ0JourneyDate=25.10.22&time=17%3A59', headers=headers) print(f"第二个链接状态码:{response2.status_code}") print(response2.text[:500])
如果requests能拿到200响应,再对比Scrapy的请求头、Cookie设置,找出差异点调整;如果requests也返回403,说明网站有更严格的反爬(如Cloudflare验证),需要用Playwright或Selenium这类工具绕过。
内容的提问来源于stack exchange,提问作者mk1319
相关产品推荐
相关产品推荐

