scrapy第一发——基础巩固
目標:爬取
http://books.toscrape.com"將該網(wǎng)站上50頁,每頁20本的書的價格、等級、書名、書的ISBN號等爬取下來并保存在mongoDB數(shù)據(jù)庫里面。
該網(wǎng)站如圖:
首先建立一個爬蟲項目,新建一個spider文件,name取值為"book"
class BookSpider(scrapy.Spider): name = 'book'整個項目的文件結(jié)構(gòu)如下
重寫start_requests函數(shù)
def start_requests(self): url = "http://books.toscrape.com" yield Request(url, self.parse_urls)再寫一個callback函數(shù)——parse_urls,用于接受處理start_requests里面發(fā)出的Request請求所得到的response。該函數(shù)主要有兩個功能,第一個功能是解析出“下一頁”的url,第二個功能是解析出“每一頁上20本書”的url;并對這些url發(fā)出請求。
來看一看這個函數(shù)怎么寫
self.parse_urls:
def parse_urls(self , response): le = LinkExtractor(restrict_css="ul.pager li.next")leBook = LinkExtractor(restrict_css="ol.row div.image_container")next = le.extract_links(response)bookLinks = leBook.extract_links(response)# 解析每一頁上20本書的links if bookLinks: for link in bookLinks: yield Request(link.url, self.parse_book)# 解析下一頁的links if next: link = next[0].urlyield Request(link, self.parse_urls)這里用到了LIinkExtractor,使用LinkExtractor提取出url還是很方便的。具體怎么用就不講了。
可以看到,解析出下一頁的url后,又將callback設(shè)置為self.parse_urls,繼續(xù)使用該函數(shù)用來處理“下一頁”;用self.parse_book函數(shù)處理每一個書本的內(nèi)容頁。
self.parse_book:
# 挖掘每一本書的信息 def parse_book(self , response): sel = response.css('div.product_main')title = sel.xpath('./h1/text()').extract_first()# 得到書名 price = sel.css('p.price_color::text').extract_first() # 得到書的價格 rank = sel.css('p.star-rating::attr(class)').re_first('star-rating ([A-Za-z]+)') # 得到書的排名等級 sel = response.css('table.table.table-striped')ISBN = sel.xpath('(.//tr)[1]/td/text()').extract_first() # 得到書的ISBN號 surplus = sel.xpath('(.//tr)[last()-1]/td/text()').re_first('\((\d+) available\)') # 得到書的庫存量 reviewers = sel.xpath('(.//tr)[last()]/td/text()').extract_first() # 得到書的reviewers數(shù)量 single = BooksItem()single['title'] = titlesingle['price'] = pricesingle['rank'] = ranksingle['ISBN'] = ISBNsingle['surplus'] = surplussingle['reviewers'] = reviewersreturn singleself.parse_book里面使用到了BooksItem對象,BooksItem定義在items.py文件里面。
items.py
import scrapy from scrapy import Item , Fieldclass BooksItem(Item): # define the fields for your item here like: # name = scrapy.Field() title = Field()price = Field()rank = Field()ISBN = Field()surplus = Field()reviewers = Field()
分別定義了書名、價格、等級、ISBN、剩余量、觀看者這六個字段。
在scrapy可以使用Item來傳遞數(shù)據(jù)。
寫到這里可以直接使用命令“scrapy crawl book -o fileName.csv”來運行該爬蟲程序了,最后數(shù)據(jù)會保存在fileName.csv文件里面。
不過前面說好了要保存在mongoDB里面呢,咱們還得修改一下piplines.py文件。在保存在數(shù)據(jù)庫之前,先進行一個處理——書本去重,這里使用書名作為去重標準。
在piplines.py文件里面實現(xiàn)去重類:DuplicatesPipeline
# 實現(xiàn)書本的去重 class DuplicatesPipeline(object): def __init__(self): self.book_set = set()def process_item(self, item, spider): title = item['title']if title in self.book_set: raise DropItem("Duplicate book found: %s " % item)self.book_set.add(title)return item
這樣就實現(xiàn)了書本去重,(注意這里的return item,它會將item數(shù)據(jù)返回給另外下一級的item pipeline繼續(xù)處理,如果有的話)
去重了我還不滿足,我還想將英鎊轉(zhuǎn)換成人民幣,那么就再實現(xiàn)一個item pipeline——PriceConvertPipeline
# 實現(xiàn)書本的價格轉(zhuǎn)換 class PriceConvertPipeline(object): exchange_rate = 8.5309 def process_item(self, item, spider): # 實現(xiàn)貨幣的匯率轉(zhuǎn)換 price = float(item['price'][1:]) * self.exchange_rateitem['price'] = '¥ %.2f' % pricereturn item
然后我們再講最后得到的item存入數(shù)據(jù)庫里面
class MongoDBPipeline(object): @classmethod def from_crawler(cls, crawler): cls.DB_URI = crawler.settings.get('MONGO_DB_URI' , 'mongodb://localhost:27017/')cls.DB_NAME = crawler.settings.get('scrapy_data' , 'MONGO_DB_NAME')return cls()def open_spider(self, spider): self.client = pymongo.MongoClient(self.DB_URI)self.db = self.client[self.DB_NAME]def close_spider(self, spider): self.client.close()def process_item(self, item, spider): collection = self.db[spider.name]post = dict(item) if isinstance(item, Item) else item collection.insert_one(post)return item
(每實現(xiàn)一個item pipeline需要在settings.py里面加入該pipeline)如圖:
ITEM_PIPELINES = {'books.pipelines.DuplicatesPipeline' : 100, 'books.pipelines.PriceConvertPipeline' : 200, 'books.pipelines.BooksPipeline': 300, 'books.pipelines.MongoDBPipeline' : 400, }后面的鍵值取值為0~1000,越小表示執(zhí)行的優(yōu)先權(quán)越大。
這樣整份工作就完成了。
總結(jié)
以上是生活随笔為你收集整理的scrapy第一发——基础巩固的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 惊了,Ubuntu的autoremove
- 下一篇: scrapy带参数的命令