[英]Yield both items and callback request in scrapy
免責聲明:我對Python和Scrapy都很陌生。
我正試圖讓我的蜘蛛從起始網址收集網址,跟隨那些收集的網址和兩者:
我希望能夠繼續這個產生項目和回調請求的過程,但我不太清楚如何做到這一點。 目前我的代碼只返回網址,沒有項目。 我顯然做錯了什么。 任何反饋將不勝感激。
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 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.