[英]How to crawl multiple-level pages to one item in Scrapy?
我找到的 Scrapy 的所有例子都在講如何爬取單個頁面,或者如何爬取多級頁面,當每個最深的頁面都保存為一個獨立的Item
時。 但是我的情況有點復雜。
例如,網站結構是:
A (List page of books)
--> B (Book summary page)
----> C (Book review pages)
----> D (Book download pages)
因此Item
的定義如下所示:
class BookItem(scrapy.Item):
name = scrapy.Field()
type = scrapy.Field()
introduction = scrapy.Field()
resources = scrapy.Field() # To be a list of ResourceItem
reviews = scrapy.Field() # To be a list of ReviewItem
# Download pages
class ResourceItem(scrapy.Item):
title = scrapy.Field()
createDate = scrapy.Field()
author = scrapy.Field()
link = scrapy.Field()
# Book reviews
class ReviewItem(scrapy.Item):
title = scrapy.Field()
createDate = scrapy.Field()
author = scrapy.Field()
content = scrapy.Field()
我怎樣才能完成BookItem
的所有字段? 我知道我可以編寫 4 種方法,例如parse_A()
、 parse_B()
、 parse_C()
和parse_D()
,而 Scrapy 通過在每個方法的末尾使用yield scrapy.Request()
允許它們成為一個工作流。
但是我應該在最深層的方法中返回什么,即parse_C()
和parse_D()
?
ResourceItem
或ReviewItem
,它將被直接保存。BookItem
,未完成的項目也將直接保存。parse_C()
parse_D()
的Request
,它也不會起作用,因為資源可能是空的(也就是說 B 頁面上可能根本沒有 C 的鏈接)。 所以parse_C()
不會被調用,留下parse_D()
未被調用,最后 D 字段未填充。您可以使用meta
參數傳遞一些數據(請參閱https://docs.scrapy.org/en/latest/topics/request-response.html )。
因此,您可以在多個請求/解析函數中填充您的項目。
顯示邏輯的快速示例:
def parse_summary(self, response):
book_item = # scrape book item here
reviews_url = # extract reviews url
resources_url = # extract resources url
return scrapy.Request(reviews_url, callback=self.parse_reviews, meta={'item': book_item, 'resources_url': resources_url })
def parse_reviews(self, response):
book_item = response.meta.get('item') # get item draft
book_item.reviews = # extract reviews here
resources_url = response.meta.get('resources_url')
return scrapy.Request(resources_url, callback=self.parse_resources, meta={'item': book_item })
def parse_resources(self, response):
book_item = response.meta.get('item') # get item draft
book_item.ressources = # extract ressources here
return book_item # once completed, return the item
希望你能明白(我對代碼執行不是很自信,只是寫下來沒有測試)。
我現在可以自己回答了。
只需yield None
或省略parse_C()
和parse_D()
中的 return 語句即可解決問題。
Scrapy 不會僅僅因為其中一個回調什么都不返回就關閉蜘蛛,但要確保請求隊列中也沒有新的回調。
因此,由於parse_B()
在完成產生子頁面 C & D 的所有請求之前不會返回None
或Item
,因此工作流不會中斷。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.