Scrapy处理嵌套Postback无法加载目标动态表格数据求助
你这次爬取失败核心是两个层面的问题,一是现有代码有低级语法错误,二是没按ASP.NET WebForm双层Postback的状态流转逻辑发请求,服务器端视图状态校验不通过,自然返回不了正确的表格内容。
现有代码的明确问题:
- 你构造
data的时候末尾多了个逗号,实际传进FormRequest的是单元素元组,不是字典,表单参数根本没被正确提交 - 只传了
__EVENTTARGET和__VIEWSTATE两个字段,漏了ASP.NET Postback校验必需的__VIEWSTATEGENERATOR、__EVENTVALIDATION、__EVENTARGUMENT等隐藏字段 - 跳过了第一层Postback步骤:目标页面的Transfers面板本身就是点击Tab后触发Postback加载的,你直接拿初始页面的视图状态参数,去请求只有在Transfers面板加载完成后才会生效的「查看转会历史」按钮接口,服务器端上下文不匹配,直接返回异常内容。
具体修复方案
1. 严格按照用户操作顺序发两次Postback请求
WebForm的视图状态是随每次请求动态更新的,不能跳步:
- 第一步:请求球员初始页面,提取全量隐藏表单字段,发第一次Postback模拟点击Transfers选项卡,拿到选项卡面板加载完成后的响应,这时候响应里的隐藏字段已经更新为Transfers面板对应的状态
- 第二步:从第一步返回的响应里重新提取全量隐藏字段,发第二次Postback模拟点击「View Transfer History」按钮,就能拿到带转会表格的正常响应
2. 不要手动拼接表单参数,用Scrapy自带方法自动补全
手动挑字段传很容易漏校验参数,直接用FormRequest.from_response()方法,它会自动提取页面里所有带name属性的隐藏input值,你只需要覆盖要修改的__EVENTTARGET等参数即可,能避免90%的参数漏传问题。
修正后的参考代码:
def transf_tab(self,response): # 第一层Postback:切换到Transfers选项卡,__EVENTTARGET值从页面Tab控件的onclick事件里取 yield FormRequest.from_response( response, formdata={ "__EVENTTARGET": "ctl00$ctl00$CPContent$CPMain$tcPlayerInfo", # 替换为实际抓到的Transfers Tab对应的target值 "__EVENTARGUMENT": "" }, dont_filter=True, callback=self.after_switch_transfer_tab ) def after_switch_transfer_tab(self, response): # 第二层Postback:点击查看转会历史按钮,使用切换Tab后更新的视图状态参数 yield FormRequest.from_response( response, formdata={ "__EVENTTARGET": "ctl00$ctl00$CPContent$CPMain$btnViewTransferHistory", "__EVENTARGUMENT": "" }, dont_filter=True, callback=self.parse_player ) def parse_player(self, response): # 这里直接解析转会表格即可 trsf_item = HtsellsItem() # 后续解析逻辑
3. 兜底排查方法
如果按上面步骤还是返回异常内容,直接打开浏览器开发者工具,清空网络请求记录后手动依次点击Transfers Tab、点击查看转会历史按钮,把两次POST请求的Form Data和你Scrapy发出的请求参数逐行对比,哪个参数值不一致就调整哪个。另外注意你贴的JS里WebForm_PostBackOptions第三个参数为true,代表开启提交前客户端校验,确保你的请求头Content-Type为标准的application/x-www-form-urlencoded,Scrapy默认的请求头一般符合要求,如果校验不通过可以手动补全和浏览器一致的Referer头。
内容的提问来源于stack exchange,提问作者crianopa
相关产品推荐
相关产品推荐

