如何使用 scrapy 触发 JS ASP.Net 下一页事件?
How to trigger a JS ASP.Net next page event using scrapy?
我正在从这个 website I start by sending a FormRequest
that yields the search result based on Wim Herman's answer on my other question
中抓取内容
我抓取了需要的东西,想移动到下一页,它不包含 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 网页上非常常见的问题。正如您现在可能知道的那样,您提到的 js 将触发 POST 请求。此 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会忽略它)
一旦您确定了问题,您可以通过将其设置为 None
.[=23= 来告诉 from_response()
方法您不希望某个特定字段出现在正文中]
fr = FormRequest.from_response(response, formdata={
'__EVENTTARGET': 'dgSearchResults$ctl24$ctl01',
'cmdSearchNew': None
})
这应该足以让您获得第 2 页的响应。
我正在从这个 website I start by sending a FormRequest
that yields the search result based on Wim Herman's answer on my other question
我抓取了需要的东西,想移动到下一页,它不包含 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 网页上非常常见的问题。正如您现在可能知道的那样,您提到的 js 将触发 POST 请求。此 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会忽略它)
一旦您确定了问题,您可以通过将其设置为 None
.[=23= 来告诉 from_response()
方法您不希望某个特定字段出现在正文中]
fr = FormRequest.from_response(response, formdata={
'__EVENTTARGET': 'dgSearchResults$ctl24$ctl01',
'cmdSearchNew': None
})
这应该足以让您获得第 2 页的响应。