当Scrapy遍历页面上找到的hrefs列表时,为什么它会开始在列表中间的某处显示已删除的项目而不是第一个href?
我从此页面上的链接列表中提取状态库信息:http://www.publiclibraries.com/。
我使用的xpath是:
//div/div/div/table/tr/td/a/@href
代码似乎工作正常,但我想知道为什么,当显示刮下的项目时,Scrapy似乎从肯塔基州,路易斯安那州,密西西比州或密苏里州开始。它实际上首先显示的是哪一个不一致,但它最终会显示所有状态(只是不在页面上找到的顺序)。
为什么不是从Alamabama开始?这与线程有关吗?如果是这样,是否有办法强制Scrapy按照它们出现在初始页面上的顺序显示它们?
蜘蛛代码:
import scrapy
import logging
from scrapy import signals
from scrapy.exceptions import NotConfigured
from tutorial.items import LibAddressItem
class DmozSpider(scrapy.Spider):
name = "us-pub-lib-physical_addresses"
allowed_domains = ["publiclibraries.com"]
start_urls = [
"http://www.publiclibraries.com/"
]
def parse(self, response):
print "#################################################################"
print response.url
print "Top level states list"
print "#################################################################"
for href in response.xpath("//div/div/div/table/tr/td/a/@href"):
url = response.urljoin(href.extract())
yield scrapy.Request(url, callback=self.parse_state_libs)
count = 0
def parse_state_libs(self, response):
print "#################################################################"
print response.url
print "#################################################################"
for sel in response.xpath('//div/div/div/table/tr'):
item = LibAddressItem()
item['city'] = sel.xpath('td[1]/text()').extract()
item['library'] = sel.xpath('td[2]/text()').extract()
item['address'] = sel.xpath('td[3]/text()').extract()
item['zip_code'] = sel.xpath('td[4]/text()').extract()
item['phone'] = sel.xpath('td[5]/text()').extract()
self.count = self.count + 1
yield item
print "#####################################"
print "The number of libraries found so far:"
print self.count
print "#####################################"
LibAddressItem:
import scrapy
class LibAddressItem(scrapy.Item):
city = scrapy.Field()
state = scrapy.Field()
library = scrapy.Field()
address = scrapy.Field()
zip_code = scrapy.Field()
phone = scrapy.Field()
最初显示的项目示例:
2015-11-19 13:59:57 [scrapy] DEBUG: Crawled (200) <GET http://www.publiclibraries.com/> (referer: None)
#################################################################
http://www.publiclibraries.com/
Top level states list
#################################################################
2015-11-19 13:59:58 [scrapy] DEBUG: Crawled (200) <GET http://www.publiclibraries.com/kentucky.htm> (referer: http://www.publiclibraries.com/)
#################################################################
http://www.publiclibraries.com/kentucky.htm
#################################################################
2015-11-19 13:59:58 [scrapy] DEBUG: Scraped from <200 http://www.publiclibraries.com/kentucky.htm>
{'address': [], 'city': [], 'library': [], 'phone': [], 'zip_code': []}
2015-11-19 13:59:58 [scrapy] DEBUG: Scraped from <200 http://www.publiclibraries.com/kentucky.htm>
{'address': [u'302 King Drive'],
'city': [u'Albany'],
'library': [u'Clinton County Public Library'],
'phone': [u'(606) 387-5989'],
'zip_code': [u'42602']}
2015-11-19 13:59:58 [scrapy] DEBUG: Scraped from <200 http://www.publiclibraries.com/kentucky.htm>
{'address': [u'1740 Central Avenue'],
'city': [u'Ashland'],
'library': [u'Boyd County Public Library'],
'phone': [u'(606) 329-0090'],
'zip_code': [u'41101']}
2015-11-19 13:59:58 [scrapy] DEBUG: Scraped from <200 http://www.publiclibraries.com/kentucky.htm>
{'address': [u'1016 Summit Road'],
'city': [u'Ashland'],
'library': [u'Summit Branch'],
'phone': [u'(606) 928-3366'],
'zip_code': []}
答案 0 :(得分:2)
Scrapy
以异步方式运行请求,有些请求可以在其他请求之前返回,因此scrapy
可以处理第一个成功返回的请求。
可以采取一些不同的措施来解决这个问题:
您可以发出请求,然后在使用meta
后继续处理以下请求:
urls = [response.urljoin(href.extract()) for href in response.xpath("//div/div/div/table/tr/td/a/@href")]
yield Request(url[0], callback=self.parse_urls, meta=dict(urls=urls, index=0))
def parse_urls(self, response):
# do your work with the current page
yield Request(response.meta['urls'][response.meta['index']+1],
meta=dict(urls=response.meta['urls'], index=response.meta['index']+1))
每个scrapy Request
对象都有一个priority
属性,可以随时更改,因此您可以在迭代时指定优先级:
for i, href in enumerate(response.xpath("//div/div/div/table/tr/td/a/@href")):
url = response.urljoin(href.extract())
yield scrapy.Request(url, callback=self.parse_state_libs, priority=1000-i)
这应该优先考虑第一个请求,但我认为这并不能完全保证你想要的东西。
也许更方便,您可以在请求中指定一些索引,以便稍后可以订购它(也可以使用meta
或项目上的字段)。
希望它有所帮助。