使用 PostBack 数据浏览页面 javascript Python Scrapy

Posted

技术标签:

【中文标题】使用 PostBack 数据浏览页面 javascript Python Scrapy【英文标题】:Crawling through pages with PostBack data javascript Python Scrapy 【发布时间】:2015-05-12 13:08:02 【问题描述】:

我正在通过 Scrapy 使用 ASP.NET 编程浏览一些目录。

要抓取的页面是这样编码的:

javascript:__doPostBack('ctl00$MainContent$List','Page$X')

其中 X 是介于 1 和 180 之间的 int。MainContent 参数始终相同。我不知道如何爬进这些。我很想在 SLE 规则中添加一些简单的东西,例如 allow=('Page$')attrs='__doPostBack',但我的猜测是我必须更复杂才能从 javascript“链接”中提取信息。

如果更容易从 javascript 代码中“取消屏蔽”每个绝对链接并将其保存到 csv,然后使用该 csv 将请求加载到新的抓取工具中,那也没关系。

【问题讨论】:

您能否展示实际的a 元素的外观(或提供指向该网站的链接)?谢谢。 exitrealty.com/… - 页码在页面底部 【参考方案1】:

这种分页并不像看起来那么简单。解决它是一个有趣的挑战。下面提供的解决方案有几个重要说明:

这里的想法是按照分页逐页在Request.meta dictionary 中的当前页面周围传递 使用regular BaseSpider,因为分页涉及一些逻辑 提供headers 伪装成真正的浏览器很重要 产生FormRequests 和dont_filter=True 很重要,因为我们基本上是向相同的URL 发出POST 请求,但参数不同

代码:

import re

from scrapy.http import FormRequest
from scrapy.spider import BaseSpider


HEADERS = 
    'X-MicrosoftAjax': 'Delta=true',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/41.0.2272.76 Safari/537.36'

URL = 'http://exitrealty.com/agent_list.aspx?firstName=&lastName=&country=USA&state=NY'


class ExitRealtySpider(BaseSpider):
    name = "exit_realty"

    allowed_domains = ["exitrealty.com"]
    start_urls = [URL]

    def parse(self, response):
        # submit a form (first page)
        self.data = 
        for form_input in response.css('form#aspnetForm input'):
            name = form_input.xpath('@name').extract()[0]
            try:
                value = form_input.xpath('@value').extract()[0]
            except IndexError:
                value = ""
            self.data[name] = value

        self.data['ctl00$MainContent$ScriptManager1'] = 'ctl00$MainContent$UpdatePanel1|ctl00$MainContent$agentList'
        self.data['__EVENTTARGET'] = 'ctl00$MainContent$List'
        self.data['__EVENTARGUMENT'] = 'Page$1'

        return FormRequest(url=URL,
                           method='POST',
                           callback=self.parse_page,
                           formdata=self.data,
                           meta='page': 1,
                           dont_filter=True,
                           headers=HEADERS)

    def parse_page(self, response):
        current_page = response.meta['page'] + 1

        # parse agents (TODO: yield items instead of printing)
        for agent in response.xpath('//a[@class="regtext"]/text()'):
            print agent.extract()
        print "------"

        # request the next page
        data = 
            '__EVENTARGUMENT': 'Page$%d' % current_page,
            '__EVENTVALIDATION': re.search(r"__EVENTVALIDATION\|(.*?)\|", response.body, re.MULTILINE).group(1),
            '__VIEWSTATE': re.search(r"__VIEWSTATE\|(.*?)\|", response.body, re.MULTILINE).group(1),
            '__ASYNCPOST': 'true',
            '__EVENTTARGET': 'ctl00$MainContent$agentList',
            'ctl00$MainContent$ScriptManager1': 'ctl00$MainContent$UpdatePanel1|ctl00$MainContent$agentList',
            '': ''
        

        return FormRequest(url=URL,
                           method='POST',
                           formdata=data,
                           callback=self.parse_page,
                           meta='page': current_page,
                           dont_filter=True,
                           headers=HEADERS)

【讨论】:

我知道巨大的“谢谢”在 SO 中是不受欢迎的,但我很乐意投反对票说出来!谢谢!这种额外的工作和要遵循的代码非常值得学习,而且超出了我的预期。 不幸的是,当我尝试使用它时得到exceptions.AttributeError: 'HtmlResponse' object has no attribute 'css' @Xodarap777 我认为你需要将 Scrapy 升级到最新版本。 你说得对,我很抱歉 - 但现在我得到 ` '__EVENTVALIDATION': re.search(r"__EVENTVALIDATION\|(.*?)\|", response.body, re.MULTILINE ).group(1), exceptions.AttributeError: 'NoneType' object has no attribute 'group'`

以上是关于使用 PostBack 数据浏览页面 javascript Python Scrapy的主要内容,如果未能解决你的问题,请参考以下文章

动态创建的用户控件无法处理 PostBack 上的事件

什么是ASP.NET中事件回传(PostBack)机制? 请给我一个具体的定义。

在 PostBack (ASP.NET) 上运行 jQuery 函数

为啥我的 PostBack 在我的 jQuery 点击事件之前发生?

WebPart 上的用户控件、PostBack / ViewState 问题

通过 Postback 在 UpdatePanel 中保留 DIV 的滚动位置