使用Scrapy爬取Steam游戏遭遇年龄验证拦截的技术求助
解决Scrapy爬取Steam游戏时年龄验证导致的去重问题
我之前也踩过Steam年龄验证的坑,确实挺闹心的——明明看到目标游戏的链接,结果因为agecheck页面被去重过滤器拦下来,死活爬不到数据。咱们一步步来解决这个问题:
核心问题拆解
Steam的年龄验证会把请求重定向到agecheck/app/xxx这类链接,Scrapy默认的去重过滤器(RFPDupeFilter)会认为这是重复URL,直接跳过后续请求,导致验证流程无法完成,自然拿不到游戏页面的数据。
具体解决方案
1. 给年龄验证请求添加dont_filter=True
最直接的办法就是让Scrapy不对年龄验证的请求做去重检查。当检测到响应是年龄验证页面时,构造验证请求并带上这个参数:
def parse_game(self, response): # 检查当前页面是否是年龄验证页 if '/agecheck/app/' in response.url: # 构造Steam年龄验证的表单数据(注意字段要和实际页面匹配) form_data = { 'ageDay': '15', 'ageMonth': 'May', 'ageYear': '1995' } # 发送表单请求,设置dont_filter=True跳过去重 yield scrapy.FormRequest( url=response.url, formdata=form_data, callback=self.parse_game, dont_filter=True ) return # 这里写正常爬取游戏数据的逻辑 game_info = { 'title': response.css('div.apphub_AppName::text').get(), 'price': response.css('div.game_purchase_price::text').get().strip(), # 其他字段... } yield game_info
这样即使是同一个agecheck链接,Scrapy也会重复处理请求,完成年龄验证后就能进入游戏详情页了。
2. 提前完成年龄验证并保留会话Cookie
Steam验证通过后会在客户端设置Cookie,后续请求带上这个Cookie就不会再触发年龄验证。可以在爬虫启动时先完成一次验证,把Cookie存下来:
def start_requests(self): # 先请求一个需要年龄验证的游戏页面,完成前置验证 yield scrapy.Request( url='https://store.steampowered.com/app/203160/Rise_of_the_Tomb_Raider/', callback=self.handle_age_verification, dont_filter=True ) def handle_age_verification(self, response): if '/agecheck/app/' in response.url: form_data = { 'ageDay': '1', 'ageMonth': 'January', 'ageYear': '1990' } yield scrapy.FormRequest( url=response.url, formdata=form_data, callback=self.start_normal_crawling, dont_filter=True ) def start_normal_crawling(self, response): # 验证成功后,Cookie已保存,开始爬取所有目标游戏链接 target_game_urls = [ 'https://store.steampowered.com/app/203160/Rise_of_the_Tomb_Raider/', 'https://store.steampowered.com/app/379720/DOOM/', # 其他游戏链接... ] for url in target_game_urls: yield scrapy.Request(url=url, callback=self.parse_game)
这种方法一劳永逸,后续所有请求都会自动带上验证后的Cookie,彻底避免年龄验证页面的干扰。
3. 自定义去重过滤器(可选)
如果不想全局禁用部分URL的去重,可以自定义过滤器,让它对agecheck链接网开一面:
# 在项目目录下新建dupefilters.py文件 from scrapy.dupefilters import RFPDupeFilter class SteamDupeFilter(RFPDupeFilter): def request_seen(self, request): # 对agecheck链接跳过去重检查 if '/agecheck/app/' in request.url: return False # 其他URL沿用默认去重逻辑 return super().request_seen(request)
然后在settings.py里配置使用自定义过滤器:
DUPEFILTER_CLASS = 'your_project_name.dupefilters.SteamDupeFilter'
额外注意事项
- 要确认Steam年龄验证表单的字段名,有时候页面会有细微变化,用浏览器开发者工具查看表单参数更准确。
- 不要频繁请求Steam服务器,建议在
settings.py里设置DOWNLOAD_DELAY = 2,避免被IP封禁。 - 如果遇到验证码,可能需要配合代理或者验证码识别工具,但大部分年龄验证场景用上面的方法就能解决。
内容的提问来源于stack exchange,提问作者Galiu




