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

标签 python asp.net web-scraping scrapy

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

PS:我原来的帖子因投票放弃而被关闭,所以我在对第一篇帖子进行了大量编辑后重新发布到这里。


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

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


A) 该过程的实际工作部分:

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

第一次搜索工作没有问题,而且我解析第一个藏宝点没有困难。

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

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

enter image description here

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

每个号码的链接(见图)调用带有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) 首先尝试模仿此行为:

为了废弃许多页面(仅限前五页),我尝试在这里 yieldformRequest.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这里的值(value)?我模拟点击关注每个新页面的用户的策略中的问题出在哪里?

完整代码可在此处下载: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 查询的工具!

就像我原来的问题中的更新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/

相关文章:

python - python中两个列表的比较

python - 在 GAE : logging vs. 数据存储上保存数据

c# - 如何使用 .skip(i).take(j) 使用 lambda 表达式导航从数据库中获取给定范围的数据行

c# - ASP.NET 即使在调试中也不调用代码

python - 抓取表信息

python - 如何使用代理下载带有 url 的 zip 文件

c# - 南希开始接受请求很慢

python - 如果浏览器不支持框架+无法直接访问框架,如何自动获取框架内容

python - 如何将爬取的数据从 Scrapy 以 csv 或 json 的形式上传到 Amazon S3?

python - 如何确保 update() 添加到字典末尾