使用JavaScript、Python和Scrapy爬取包含PostBack数据的页面

10

我正在通过Scrapy进行ASP.NET编程来爬取一些目录。

需要爬取的页面编码如下:

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

其中,X是介于1和180之间的整数,MainContent参数始终相同。我不知道如何进入这些页面。我希望能够将SLE规则中的内容添加得更简单些,例如allow=('Page$')attrs='__doPostBack',但我猜想必须使用更加巧妙的方法才能从javascript "link"中提取信息。

如果从javascript代码中“解除”每个绝对链接并将其保存到csv文件中,然后使用该csv文件将请求加载到新的网页爬虫中,那也可以。


你能展示一下实际的 a 元素是什么样子的(或者提供一个网站链接)吗?谢谢。 - alecxe
1个回答

19

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

代码:

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)

4
我知道在 Stack Overflow 上太多“非常感谢”的话会不被看好,但是我愿意冒着被踩的风险来表达!非常感谢你们!这种额外的工作和代码实践对于学习来说非常棒,超出了我的预期。 - Xodarap777
很不幸,当我尝试使用这个时,我会得到“exceptions.AttributeError: 'HtmlResponse' object has no attribute 'css'”异常。 - Xodarap777
@Xodarap777,我认为你需要将Scrapy升级到最新版本。 - alecxe
2
你是对的,我道歉 - 但现在我得到了'__EVENTVALIDATION': re.search(r"__EVENTVALIDATION\|(.*?)\|", response.body, re.MULTILINE).group(1), exceptions.AttributeError: 'NoneType' object has no attribute 'group' - Xodarap777

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接