【问题标题】:How to trigger a JS ASP.Net next page event using scrapy?如何使用 scrapy 触发 JS ASP.Net 下一页事件?
【发布时间】:2020-12-13 05:59:15
【问题描述】:

我正在从这个website 中抓取内容我首先发送一个FormRequest,它会根据Wim Herman's 对我的另一个问题here 的回答产生搜索结果

我抓取了需要的内容并想移动到不包含 url 的下一页,它是由 JS 触发的。下面是 html 标签的样子:

<a href="javascript:__doPostBack('dgSearchResults$ctl24$ctl01','')">2</a>

我尝试了以下方法,但似乎没有任何效果:

In [18]: fr = FormRequest.from_response(response, formdata={"__EVENTTARGET": 'dg
    ...: SearchResults$ctl02$ctl03'})                                           

In [19]: fetch(fr)                                                              
2020-08-24 16:47:06 [scrapy.core.engine] DEBUG: Crawled (200) <POST https://registers.maryland.gov/RowNetWeb/Estates/frmEstateSearch2.aspx> (referer: None)

In [20]: view(response)                                                         
Out[20]: True

还有这个:

In [21]: fr = FormRequest.from_response(response, formdata={"__EVENTTARGET": 'dg
    ...: SearchResults$ctl02$ctl01'}, clickdata={'type': 'submit'})             

In [22]: fetch(fr)                                                              
2020-08-24 16:50:24 [scrapy.core.engine] DEBUG: Crawled (200) <POST https://registers.maryland.gov/RowNetWeb/Estates/frmEstateSearch2.aspx> (referer: None)

In [23]: view(response)                                                         
Out[23]: True

当我查看响应时,它要么让我进入初始页面(包含初始表单的页面),要么什么也没发生,页码仍设置为 1。

【问题讨论】:

  • 这在 ASP 网页中很常见。 from_response 非常适合处理这些问题,但有时它会跳过必填字段,或者包含不应出现在请求正文中的字段。在生成之前尝试检查您的request.body,并将其与浏览器在更改页面时发出的 POST 请求的正文进行比较。如果相同,您可能还需要重新生成标题。
  • 你能详细说明吗?
  • 当然,到时会写一个正确的答案。

标签: javascript asp.net scrapy dom-events


【解决方案1】:

正如我在评论中提到的,这是 ASP 网页上非常常见的问题。正如您现在可能知道的那样,您提到的 js 将触发 POST 请求。此帖子请求的正文可能包含您在搜索表单中作为输入填写的字段以及页面实例生成的几个隐藏输入(如 __VIEWSTATE__VIEWSTATEGENERATOR )。

当您使用FormRequest.from_response() 方法时,它会搜索这些输入来填充请求正文,它通过选择页面中//form 元素内的所有输入元素来实现。有时可以,有时不行,这就是你的情况。

当该方法选择所有输入时,它会获得一个用于其他用途的输入。在你的情况下是这个输入:

<input id="cmdSearchNew" value="New Search" ... />

你怎么知道?

如果您使用浏览器的开发工具并分析从第 1 页更改为第 2 页的请求是如何产生的,您会发现这是一个 POST 请求,其正文如下所示:

{
    "__EVENTTARGET":"dgSearchResults$ctl24$ctl01",
    "__EVENTARGUMENT":"",
    "__VIEWSTATE":"jyAD4Bm...",
    "__VIEWSTATEGENERATOR":"11C1F95B",
    "__EVENTVALIDATION":"TmG0xFB..."
}

但是,如果你检查你的 scrapy 请求的正文(你可以在你已经使用的 shell 中打印你的fr.body)你会看到这样的东西:

{
    "__EVENTTARGET":"dgSearchResults$ctl24$ctl01",
    "cmdSearchNew": "New Search"
    "__VIEWSTATE":"jyAD4Bm...",
    "__VIEWSTATEGENERATOR":"11C1F95B",
    "__EVENTVALIDATION":"TmG0xFB..."
}

会被urlencoded,这是一个解析过的视图

cmdSearchNew 字段不应该存在,它是用于其他用途的,但scrapy 无法知道,因为它在同一个表单中。 (另外__EVENTARGUMENT不会出现,因为值为空,所以Scrapy会忽略它)

一旦您发现了问题,您可以告诉from_response() 方法您不希望特定字段出现在正文中,方法是将其设置为None

fr = FormRequest.from_response(response, formdata={
    '__EVENTTARGET': 'dgSearchResults$ctl24$ctl01',
    'cmdSearchNew': None
})

这应该足以让您获得第 2 页的响应。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 2011-12-03
    • 2023-03-11
    相关资源
    最近更新 更多