Scrapy:FormRequest 不会自动填充 ASP.net 隐藏字段

Posted

技术标签:

【中文标题】Scrapy:FormRequest 不会自动填充 ASP.net 隐藏字段【英文标题】:Scrapy: FormRequest doesn't auto-populate ASP.net hidden fields 【发布时间】:2014-06-27 22:39:00 【问题描述】:

我正在使用 Scrapy 来抓取身份验证屏幕后面的一些金子。该网站使用ASP.net,而ASP 的表单中到处都是一些愚蠢的隐藏字段(如__VIEWSTATE__EVENTTARGET)。

当我调用 FormRequest.from_response(response,... 时,我希望它会自动从响应中读取这些隐藏字段并将它们填充到 formdata 字典中 - 这是 Scrapy's FormRequest 文档所说的 应该做。

但如果是这样,那为什么登录过程只有在我明确列出这些字段并填充它们时才起作用?

class ItsyBitsy(Spider):
    name = "itsybitsy"
    allowed_domains = ["website.com"]
    start_urls = ["http://website.com/cpanel/Default.aspx"]

    def parse(self, response):
        # Performs authentication to get past the login form
        sel = Selector(response)
        return [FormRequest.from_response(response,
        formdata=
        'tb_Username':'admin',
        'tb_Password':'password',

        # The following fields should be auto populated, right?
        # So why does removing 'em break the login (w/500 Server Error)
        '__VIEWSTATE':
              sel.xpath("//input[@name='__VIEWSTATE']/@value").extract(),
        '__EVENTVALIDATION':
              sel.xpath("//input[@name='__EVENTVALIDATION']/@value").extract(),
        '__EVENTTARGET': 'b_Login'

        ,
        callback=self.after_login,
        clickdata='id':'b_Login',
        dont_click=True)]

    def after_login(self, response):
        # Mmm, scrumptious
        pass

编辑:添加表单 html

<form id="form1" action="Default.aspx" method="post" name="form1">
<div>
<input type="hidden" value="" id="__EVENTTARGET" name="__EVENTTARGET">
<input type="hidden" value="" id="__EVENTARGUMENT" name="__EVENTARGUMENT">
<input type="hidden" value="/wEPDwULLTE2OTg2NjA1NTAPZBYCAgMPZBYGAgMPD2QWAh4Kb25rZXlwcmVzcwUlcmV0dXJuIGNsaWNrQnV0dG9uKGV2ZW50LCAnYl9Mb2dpbicpO2QCBQ8PZBYCHwAFJXJldHVybiBjbGlja0J1dHRvbihldmVudCwgJ2JfTG9naW4nKTtkAgcPD2QWAh4Hb25jbGljawUPcmV0dXJuIGxvZ2luKCk7ZGRKt/WTOQThVTxB9Y0QcIuRqylCIw==" id="__VIEWSTATE" name="__VIEWSTATE">
</div>

<script type="text/javascript">
//&lt;![CDATA[
var theForm = document.forms['form1'];
if (!theForm) 
theForm = document.form1;

function __doPostBack(eventTarget, eventArgument) 
if (!theForm.onsubmit || (theForm.onsubmit() != false)) 
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();


//]]&gt;
</script>


<div>

<input type="hidden" value="/wEWBAK0o8DDCQLxz5rcDwLF8dCIDALHyYWSA+rA4VJNaEpFIycMDHQPUOz393TI" id="__EVENTVALIDATION" name="__EVENTVALIDATION">
<input type="text" onkeypress="return clickButton(event, 'b_Login');" size="28" class="textfield-text" id="tb_Username" name="tb_Username">
<input type="password" onkeypress="return clickButton(event, 'b_Login');" size="28" class="textfield-text" id="tb_Password" name="tb_Password">
<a href="javascript:__doPostBack('b_Login','')" class="button-link" id="b_Login" onclick="return login();">Login</a>
</form>

【问题讨论】:

请在输入的位置显示form标签的内容。 @alecxe 完成。应该不会有太大区别,因为我显然可以使用 XPATH 检索它吗? 我猜有多种形式。可以将'formname':'form1' 添加到formdata 字典中进行测试吗? @sp1der 它没有按预期工作。身份验证后请求下一页时,我得到一个302 回到登录页面。 【参考方案1】:

根据source code,Scrapy 使用以下 CSS 选择器将输入解析出表单:

descendant::textarea|descendant::select|descendant::input[@type!="submit" and @type!="image" and @type!="reset"and ((@type!="checkbox" and @type!="radio") or @checked)]

换句话说,您的所有隐藏输入都已成功解析(并在稍后随请求一起发送),其值等于value 属性。所以,Scrapy 在这里做了它应该做的。

使用from_response() 登录不起作用,因为__EVENTTARGET 有一个空的value 属性。如果您使用真实浏览器登录,__EVENTTARGET 参数值将通过 javascript __doPostBack() 函数调用设置为 b_Login。并且,由于 Scrapy 不能处理 javascript(不能调用 js 函数),__EVENTTARGET 被发送一个空值导致登录失败。

__EVENTARGUMENT 也有一个空的value,但它实际上在__doPostBack() 函数中设置为空字符串,所以在这里没有什么区别。

希望对您有所帮助。

【讨论】:

谢谢亚历克斯。不过只有一个问题——如果是这样的话,为什么 XPATH 语句会正确检索隐藏字段(如果它们是通过 Javascript 填充的,并且 Scrapy 不执行 javascript 函数)? @FloatingRock 当然,除了__EVENTTARGET__EVENTARGUMENT 之外的每个字段都有一个非空的value attribute。 __EVENTARGUMENT 不相关,因为它总是空的。 __EVENTTARGET 值您必须手动设置为b_login。希望这对你有意义。 啊,我明白了。所以我只需要手动设置__EVENTTARGET,其他所有东西实际上都由 Scrapy 填充。测试了它,它工作!谢谢!!

以上是关于Scrapy:FormRequest 不会自动填充 ASP.net 隐藏字段的主要内容,如果未能解决你的问题,请参考以下文章

scrapy--模拟登陆

scrapy formRequest 表单提交

Scrapy FormRequest 发送 JSON

Scrapy FormRequest返回400错误代码

Scrapy的FormRequest没有给出结果

登录时FormRequest Scrapy出现问题