You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用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

火山引擎 最新活动