簡體   English   中英

在scrapy中產生項目和回調請求

[英]Yield both items and callback request in scrapy

免責聲明:我對Python和Scrapy都很陌生。

我正試圖讓我的蜘蛛從起始網址收集網址,跟隨那些收集的網址和兩者:

  1. 抓取下一頁的具體項目(並最終返回)
  2. 從下一頁收集更具體的網址,並按照這些網址進行操作。

我希望能夠繼續這個產生項目和回調請求的過程,但我不太清楚如何做到這一點。 目前我的代碼只返回網址,沒有項目。 我顯然做錯了什么。 任何反饋將不勝感激。

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.禁用JS時無法使用生物URL。 在瀏覽器中關閉JS並查看此頁面: https//votesmart.org/candidate/126288/derek-stanford

您應該看到標記為空href並在注釋下隱藏正確的URL。

<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>-->

要提取生物URL,您可以使用xpath選擇器“/ comment()”獲取此注釋,然后使用regexp提取url。

或者,如果url結構對於所有頁面都是通用的,只需自己形成url:將“/ 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM