我已經編寫了scrapy crawlspider來抓取具有類似頁面>類型頁面>列表頁面>項目頁面的結構的站點。在類別頁面上有許多類別的機器,每類機器都有一個類型很多的類型頁面,每種不同類型都有一個項目列表,最後每臺機器都有一個包含它的信息的頁面。Scrapy:抓取頁面不會生成嵌套回調中的所有鏈接
我的蜘蛛有一個規則,從主頁獲取到我定義回調parsecatpage的類別頁面,這會生成一個項目,抓取該類別併爲頁面上的每個類別生成一個新請求。我通過request.meta傳遞項目和類別名稱,並指定回調爲parsetype頁面。
Parsetypepage從response.meta獲取項目,然後爲每個類型生成請求並傳遞該項目,並將request.meta中的類別和類型連接在一起。回調是parsemachinelist。
Parsemachinelist從response.meta獲取項目,然後爲列表中的每個項目生成請求,並通過request.meta將項目,類別/類型,描述傳遞給最終回調parsemachine。這將獲取元屬性,並使用頁面上的信息和前一頁傳遞的信息填充項目中的所有字段,最後生成一個項目。
如果我將其限制爲單個類別並鍵入(例如contains[@href, "filter=c:Grinders"]
和contains[@href, "filter=t:Disc+-+Horizontal%2C+Single+End"]
),那麼它就起作用,並且最終頁面上的每臺機器都有一個機器項目。問題在於,一旦我允許蜘蛛對所有類別和所有類型進行scrapy處理,它就會在返回的最後一頁的第一個頁面中返回機器的scrapy項目,一旦它完成,蜘蛛就完成了,獲得其他類別等
這裏是(匿名)代碼
from scrapy.selector import HtmlXPathSelector
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.http import Request
from myspider.items import MachineItem
import urlparse
class MachineSpider(CrawlSpider):
name = 'myspider'
allowed_domains = ['example.com']
start_urls = ['http://www.example.com/index.php']
rules = (
Rule(SgmlLinkExtractor(allow_domains=('example.com'),allow=('12\.html'),unique=True),callback='parsecatpage'),
)
def parsecatpage(self, response):
hxs = HtmlXPathSelector(response)
#this works, next line doesn't categories = hxs.select('//a[contains(@href, "filter=c:Grinders")]')
categories = hxs.select('//a[contains(@href, "filter=c:Grinders") or contains(@href, "filter=c:Lathes")]')
for cat in categories:
item = MachineItem()
req = Request(urlparse.urljoin(response.url,''.join(cat.select("@href").extract()).strip()),callback=self.parsetypepage)
req.meta['item'] = item
req.meta['machinecategory'] = ''.join(cat.select("./text()").extract())
yield req
def parsetypepage(self, response):
hxs = HtmlXPathSelector(response)
#this works, next line doesn't types = hxs.select('//a[contains(@href, "filter=t:Disc+-+Horizontal%2C+Single+End")]')
types = hxs.select('//a[contains(@href, "filter=t:Disc+-+Horizontal%2C+Single+End") or contains(@href, "filter=t:Lathe%2C+Production")]')
for typ in types:
item = response.meta['item']
req = Request(urlparse.urljoin(response.url,''.join(typ.select("@href").extract()).strip()),callback=self.parsemachinelist)
req.meta['item'] = item
req.meta['machinecategory'] = ': '.join([response.meta['machinecategory'],''.join(typ.select("./text()").extract())])
yield req
def parsemachinelist(self, response):
hxs = HtmlXPathSelector(response)
for row in hxs.select('//tr[contains(td/a/@href, "action=searchdet")]'):
item = response.meta['item']
req = Request(urlparse.urljoin(response.url,''.join(row.select('./td/a[contains(@href,"action=searchdet")]/@href').extract()).strip()),callback=self.parsemachine)
print urlparse.urljoin(response.url,''.join(row.select('./td/a[contains(@href,"action=searchdet")]/@href').extract()).strip())
req.meta['item'] = item
req.meta['descr'] = row.select('./td/div/text()').extract()
req.meta['machinecategory'] = response.meta['machinecategory']
yield req
def parsemachine(self, response):
hxs = HtmlXPathSelector(response)
item = response.meta['item']
item['machinecategory'] = response.meta['machinecategory']
item['comp_name'] = 'Name'
item['description'] = response.meta['descr']
item['makemodel'] = ' '.join([''.join(hxs.select('//table/tr[contains(td/strong/text(), "Make")]/td/text()').extract()),''.join(hxs.select('//table/tr[contains(td/strong/text(), "Model")]/td/text()').extract())])
item['capacity'] = hxs.select('//tr[contains(td/strong/text(), "Capacity")]/td/text()').extract()
relative_image_url = hxs.select('//img[contains(@src, "custom/modules/images")]/@src')[0].extract()
abs_image_url = urlparse.urljoin(response.url, relative_image_url.strip())
item['image_urls'] = [abs_image_url]
yield item
SPIDER = MachineSpider()
因此,例如,蜘蛛會發現類別頁面上磨牀,並轉到磨牀類型的頁面,它會找到光盤水平Single End類型,然後它將進入該頁面並找到機器列表並轉到每個機器頁面,最後每個機器都會有一個項目。如果您嘗試去磨牀和車牀,雖然它將通過磨牀磨合,但它會抓取車牀和車牀類型頁面,並在那裏停止,而不會產生對車牀列表頁面和最終車牀頁面的請求。
任何人都可以幫忙嗎?爲什麼一旦有多於一種類型的機器,蜘蛛就不會進入第二個(或第三個)機器列表頁面?
對不起,史詩般的文章,只是試圖解釋問題!
謝謝!
如果您在本網站上發現任何有用的答案/問題,請立即投訴 – warvariuc 2012-03-16 12:03:56