在scrapy中产生项目和回调请求

时间:2016-09-01 02:04:50

标签: python callback scrapy

免责声明:我对Python和Scrapy都很陌生。

我正试图让我的蜘蛛从起始网址收集网址,关注那些收集的网址以及两者:

  1. 抓取下一页的特定项目(并最终返回)
  2. 从下一页收集更具体的网址,并按照这些网址进行操作。
  3. 我希望能够继续这个产生项目和回调请求的过程,但我不太清楚如何做到这一点。 目前我的代码只返回网址,没有项目。我显然做错了什么。任何反馈将不胜感激。

    class VSSpider(scrapy.Spider):
        name = "vs5"
        allowed_domains = ["votesmart.org"]
        start_urls = [
                      "https://votesmart.org/officials/WA/L/washington-state-legislative#.V8M4p5MrKRv",
                      ]
    
        def parse(self, response):
            sel = Selector(response)
            #this gathers links to the individual legislator pages, it works
            for href in response.xpath('//h5/a/@href'): 
                url = response.urljoin(href.extract())
                yield scrapy.Request(url, callback=self.parse1)
    
        def parse1(self, response):
            sel = Selector(response)
            items = []
            #these xpaths are on the next page that the spider should follow, when it first visits an individual legislator page
            for sel in response.xpath('//*[@id="main"]/section/div/div/div'):
                item = LegislatorsItems()
                item['current_office'] = sel.xpath('//tr[1]/td/text()').extract()
                item['running_for'] = sel.xpath('//tr[2]/td/text()').extract()
                items.append(item)
            #this is the xpath to the biography of the legislator, which it should follow and scrape next
            for href in response.xpath('//*[@id="folder-bio"]/@href'):
                url = response.urljoin(href.extract())
                yield scrapy.Request(url, callback=self.parse2, meta={'items': items})
    
        def parse2(self, response):
            sel = Selector(response)
            items = response.meta['items']
            #this is an xpath on the biography page
            for sel in response.xpath('//*[@id="main"]/section/div[2]/div/div[3]/div/'):
                item = LegislatorsItems()
                item['tester'] = sel.xpath('//div[2]/div[2]/ul/li[3]').extract()
                items.append(item)
                return items
    

    谢谢!

1 个答案:

答案 0 :(得分:2)

您的问题有两个级别。

1。生效网址不适用于已停用的JS。在浏览器中关闭JS并检查此页面: https://votesmart.org/candidate/126288/derek-stanford

您应该看到标记为空href,并在注释下隐藏正确的网址。

<a href="#" class="folder" id="folder-bio">
<!--<a href='/candidate/biography/126288/derek-stanford' itemprop="url" class='more'>
           See Full Biographical and Contact Information</a>-->

要提取生物网址,您可以使用xpath选择器“/ comment()”获取此评论,然后使用regexp提取网址。

或者,如果网址结构对所有网页都很常见,请自行填写网址:将“/ candidate /”替换为“/ candidate / tradition /".

  

NB!如果您遇到意外问题,首先要采取行动之一 - 禁用JS并在Scrapy看到该页面时查看该页面。测试所有选择器。

2。您对商品的使用非常复杂。如果“一个项目=一个人”,您应该在“parse_person”中定义一个项目并将其传递给“parse_bio”。

查看更新后的代码。我在找到问题时重写了一些部分。注意:

  • 您不需要(在大多数情况下)创建“项目”列表并向其追加项目。 Scrapy自己管理物品。
  • “sel = Selector(response)”在您的代码中没有意义,您可以抛出它。

此代码使用Scrapy 1.0和Python 3.5进行测试,但早期版本也可以使用。

from scrapy import Spider, Request

class VSSpider(Spider):
    name = "vs5"
    allowed_domains = ["votesmart.org"]
    start_urls = ["https://votesmart.org/officials/WA/L/washington-state-legislative"]

    def parse(self, response):
        for href in response.css('h5 a::attr(href)').extract():
            person_url = response.urljoin(href)
            yield Request(person_url, callback=self.parse_person)

    def parse_person(self, response):  # former "parse1"
        # define item, one for both parse_person and bio function
        item = LegislatorsItems()

        # extract text from left menu table and populate to item
        desc_rows = response.css('.span-abbreviated td::text').extract()
        if desc_rows:
            item['current_office'] = desc_rows[0]
            item['running_for'] = desc_rows[1] if len(desc_rows) > 1 else None

        # create right bio url and pass item to it
        bio_url = response.url.replace('votesmart.org/candidate/', 
                                       'votesmart.org/candidate/biography/')
        return Request(bio_url, callback=self.parse_bio, meta={'item': item})

    def parse_bio(self, response):  # former "parse2"
        # get item from meta, add "tester" data and return
        item = response.meta['item']
        item['tester'] = response.css('.item.first').xpath('//li[3]').extract()
        print(item)   # for python 2: print item 
        return item
相关问题