gpt4 book ai didi

python - 为 asp doPostBack() 函数生成正确的 scrapy 隐藏输入表单值

转载 作者:太空宇宙 更新时间:2023-11-04 02:33:22 25 4
gpt4 key购买 nike

tldr; 我试图覆盖服务器所需的隐藏字段以返回一个新的地理缓存页面失败(__EVENTTARGET 属性),因此服务器返回一个空页面.

Ps:我的原始帖子因投票放弃而关闭,所以我在对第一篇帖子进行大量编辑后重新发布。


我尝试使用 Scrapy 1.5.0 抓取一些包含著名地理藏宝网站缓存的网页。

因为如果你想运行这个code,你需要一个帐户,我在网站上创建了一个新的临时免费帐户来进行一些测试:dumbuser 密码为 stackoverflow


A) 流程的实际工作部分:

  • 首先,我通过登录页面(需要搜索页面)进入网站:https://www.geocaching.com/account/login
  • 成功登录后,我在某些地理位置(例如法国,上诺曼底)搜索项目(geocaches)。

这第一次搜索没有问题,我很容易解析第一个 geocaches。

B) 过程中的问题部分:请求下一页

当我尝试模拟点击转到地理藏宝的下一页时。例如转到第 1 页到第 2 页。

enter image description here

网站使用ASP with synchronised state between client and server ,因此我们需要先转到 page1,然后是 page2,然后是 page3,然后在抓取期间以此类推,以维护服务器在每个 FORM 查询之间生成的 __VIEWSTATE 变量(隐藏输入)。

每个数字的链接(见图片)调用一个带有 javascript 函数的链接 javascript:__doPostBack(...),在提交整个表单之前将内容注入(inject)到已经存在的隐藏字段中。

正如您在 __doPostBack 函数中所见:

<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['aspnetForm'];
if (!theForm) {
theForm = document.aspnetForm;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>

例子:因此,当您单击第 2 页链接时,javascript 运行是 javascript:__doPostBack('ctl00$ContentBody$pgrTop$lbGoToPage_2','')。表单与

一起提交
  • __EVENTTARGET = ctl00$ContentBody$pgrTop$lbGoToPage_2
  • __EVENTARGUMENT = ''

C) 首先尝试模仿这种行为:

为了废弃许多页面(这里限制为五个第一页)我在这里尝试 yield 五个 formRequest.from_response 查询,它只是手动覆盖这个 __EVENTTARGET __EVENTARGUMENT 属性:

def parse_pages(self,response):

self.parse_cachesList(response)

## EXTRACT NUMBER OF PAGES
links = response.xpath('//td[@class="PageBuilderWidget"]/span/b[3]')
print(links.extract_first())

## Try to extract page 1 to 5 for exemple
for page in range(1,5):
yield scrapy.FormRequest.from_response(
response,
formxpath="//form[@id='aspnetForm']",
formdata=
{'__EVENTTARGET':'ctl00$ContentBody$pgrTop$lbGoToPage_'+str(page),
'__EVENTARGUMENT': '',
'__LASTFOCUS': ''},
dont_click=True,
callback=self.parse_cachesList,
dont_filter=True
)

D) 后果:

服务器返回的页面是空的,所以我的策略有问题。

当我查看表单发布后服务器返回的生成的 html 代码时,__EVENTTARGET 永远不会被 scrapy 覆盖:

<input id="__EVENTTARGET" name="__EVENTTARGET" type="hidden" value=""/>
<input id="__EVENTARGUMENT" name="__EVENTARGUMENT" type="hidden" value=""/>

E) 问题:

你能帮我理解为什么 scrapy 不替换/覆盖这里的 __EVENTTARGET 值吗?我模拟点击关注每个新页面的用户的策略中的问题在哪里?

完整代码可在此处下载:code


更新 1:

使用 fiddler,我终于发现问题与输入有关:ctl00$ContentBody$chkAll=Check All 此输入由 scrapy.FormRequest.from_response 方法自动复制。如果我从 POST 请求中删除此属性,它就可以工作。那么,我怎样才能删除这个字段,我尝试清空没有结果:

result = scrapy.FormRequest.from_response(
response,
formname="aspnetForm",
formxpath="//form[@id='aspnetForm']",
formdata={'ctl00$ContentBody$chkAll':'',
'__EVENTTARGET':'ctl00$ContentBody$pgrTop$lbGoToPage_2',},
dont_click=True,
callback=self.parse_cachesList,
dont_filter=True,
meta={'proxy': 'http://localhost:8888'}
)

最佳答案

已解决 使用大量耐心,fiddler调试 POST 查询并将其重新发送到服务器的工具!

就像update 1在我原来的问题中说的那样,问题来自表单中的输入ctl00$ContentBody$chkAll

FormRequest 发送的 POST 表单中删除输入的方法很简单,我在 commit here 中找到了它.在 formdata 字典中将该属性设置为 None

    result = scrapy.FormRequest.from_response(
response,
formname="aspnetForm",
formxpath="//form[@id='aspnetForm']",
formdata={'ctl00$ContentBody$chkAll':None,
'__EVENTTARGET':'ctl00$ContentBody$pgrTop$lbGoToPage_2',},
dont_click=True,
callback=self.parse_cachesList,
dont_filter=True
)

关于python - 为 asp doPostBack() 函数生成正确的 scrapy 隐藏输入表单值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48544207/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com