柚子快報邀請碼778899分享:Scrapy爬蟲框架實戰(zhàn)
柚子快報邀請碼778899分享:Scrapy爬蟲框架實戰(zhàn)
Python實現(xiàn)爬蟲是很容易的,一般來說就是獲取目標網(wǎng)站的頁面,對目標頁面的分析、解析、識別,提取有用的信息,然后該入庫的入庫,該下載的下載。以前寫過一篇文章《Python爬蟲獲取電子書資源實戰(zhàn)》,以一個電子書的網(wǎng)站為例來實現(xiàn)python爬蟲獲取電子書資源。爬取整站的電子書資源,按目錄保存到本地,并形成索引文件方便查找。這次介紹通過Scrapy爬蟲框架來實現(xiàn)同樣的功能。
一、Scrapy簡介
Scrapy 是用 Python 實現(xiàn)的一個為了爬取網(wǎng)站數(shù)據(jù)、提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架。 Scrapy 常應(yīng)用在包括數(shù)據(jù)挖掘,信息處理或存儲歷史數(shù)據(jù)等一系列的程序中。 通常我們可以很簡單的通過 Scrapy 框架實現(xiàn)一個爬蟲,抓取指定網(wǎng)站的內(nèi)容或圖片。
Scrapy Engine(引擎):負責Spider、ItemPipeline、Downloader、Scheduler中間的通訊,信號、數(shù)據(jù)傳遞等。Scheduler(調(diào)度器):它負責接受引擎發(fā)送過來的Request請求,并按照一定的方式進行整理排列,入隊,當引擎需要時,交還給引擎。Downloader(下載器):負責下載Scrapy Engine(引擎)發(fā)送的所有Requests請求,并將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理,Spider(爬蟲):它負責處理所有Responses,從中分析提取數(shù)據(jù),獲取Item字段需要的數(shù)據(jù),并將需要跟進的URL提交給引擎,再次進入Scheduler(調(diào)度器).Item Pipeline(管道):它負責處理Spider中獲取到的Item,并進行進行后期處理(詳細分析、過濾、存儲等)的地方。Downloader Middlewares(下載中間件):可以當作是一個可以自定義擴展下載功能的組件。Spider Middlewares(Spider中間件):可以理解為是一個可以自定擴展和操作引擎和Spider中間通信的功能組件(比如進入Spider的Responses;和從Spider出去的Requests)
二、Scrapy實戰(zhàn)
雖然用python寫一個爬蟲也不是很費事,但是有了Scrapy以后讓你實現(xiàn)爬蟲更簡單,更加通用,現(xiàn)在我們還是以《Python爬蟲獲取電子書資源實戰(zhàn)》中的例子,爬取目標網(wǎng)站kgbook.com。也可以對比看一下通過Scrapy爬蟲框架實現(xiàn)相同的功能有多么的方便。
1、Scrapy安裝
首先通過 pip 安裝 Scrapy 框架
pip install Scrapy
2、創(chuàng)建Scrapy項目工程
創(chuàng)建getbooks的項目
scrapy startproject getbooks
創(chuàng)建一個getkgbook的爬蟲,目標網(wǎng)站kgbook.com
scrapy genspider getkgbook kgbook.com
項目的結(jié)構(gòu)如下圖所示
3、實現(xiàn)Scrapy的爬蟲代碼
爬數(shù)據(jù)
主要的爬蟲邏輯實現(xiàn)代碼都在getkgbook.py中,在這里實現(xiàn)目錄的爬取、翻頁、進入到詳情頁,并解析詳情頁的數(shù)據(jù)。 getkgbook.py
import os
import re
import scrapy
from getbooks.items import KgbookItem
class GetkgbookSpider(scrapy.Spider):
name = "getkgbook" #爬蟲的名稱
allowed_domains = ["kgbook.com"] #爬取的網(wǎng)站
start_urls = ["https://kgbook.com"] #爬取的首頁
def parse(self, response):
categorys = response.xpath('//div[@id="category"]/div/ul/li/a')
for category in categorys:
category_url = category.xpath('./@href').extract_first()
url=response.urljoin(category_url)
#爬取進入到目錄頁
yield response.follow(url, self.parse_booklist)
#解析目錄頁
def parse_booklist(self,response):
book_list_select=response.css('.channel-item h3.list-title a')
#獲取書籍列表
for book_info_select in book_list_select:
book_name=book_info_select.css('::text').extract_first()
book_detail_url=book_info_select.css('::attr(href)').extract_first()
book_detail_url=response.urljoin(book_detail_url)
print(book_name,book_detail_url)
yield scrapy.Request(url=book_detail_url, callback=self.pase_bookdetail)
#翻頁
nextpage_url = response.xpath('//div[@class="pagenavi"]/a[contains(text(), "下一頁")]/@href').extract_first()
if nextpage_url:
yield response.follow(nextpage_url, self.parse_booklist)
#解析詳情頁
def pase_bookdetail(self,response):
navegate=response.xpath('//nav[@id="location"]/a')
if len(navegate)>1:
book_category=navegate[1].xpath('./text()').extract_first()
book_name=response.css('.news_title::text').extract_first()
book_author=response.xpath('//div[@id="news_details"]/ul/li[contains(text(),"作者")]/text()').extract_first()
pattern=re.compile('mobi|epub|azw3|pdf',re.I) #解析書籍的類型
book_download_urls=response.xpath('//div[@id="introduction"]/a[@class="button"]')
for book_download_urlinfo in book_download_urls:
book_type=book_download_urlinfo.re(pattern)
if book_type:
book_download_url=book_download_urlinfo.xpath('./@href').extract_first()
#獲取要下載的書籍的名稱、作者、要保存的路徑、下載地址
item=KgbookItem()
item['book_name']=book_name
item['book_author']=book_author
item['book_file']=os.path.join(book_category,book_name+"."+str(book_type[0]).lower())
item['book_url']=book_download_url
print(book_name,book_author,book_download_url,item['book_file'])
return item
在這里我們通過xpath解析器和css解析器來解析獲取網(wǎng)頁中的有用的信息。如提取a 標簽的href的信息 ,提取書籍的名稱、作者、下載鏈接等信息。
保存數(shù)據(jù)
item.py 在item.py中定義了KgbookItem類,Item 定義結(jié)構(gòu)化數(shù)據(jù)字段,用來保存爬取到的數(shù)據(jù),有點像 Python 中的 dict,但是提供了一些額外的保護減少錯誤。在這里定義了book_name、book_author、book_file、book_url這些信息都會通過爬蟲提取后保存用來輸出到文件或數(shù)據(jù)庫等。
import scrapy
class KgbookItem(scrapy.Item):
book_name=scrapy.Field()
book_author=scrapy.Field()
book_file=scrapy.Field()
book_url=scrapy.Field()
下載數(shù)據(jù)
通過pipelines定義文件下載的管道類 pipelines.py
from scrapy import item, Request
from scrapy.pipelines.files import FilesPipeline
class KgBookFilePipeline(FilesPipeline):
def get_media_requests(self,item,info):
yield Request(item['book_url'],meta={'book_file':item['book_file']})
def file_path(self, request, response=None, info=None):
file_name=request.meta.get('book_file')
return file_name
這里實際上只做兩件事,一是get_media_requests下載文件,二是組織文件要保存的路徑。會通過相應(yīng)的下載中間件將文件下載并保存在需要保存的目錄。這里我們規(guī)劃的保存目錄是書籍目錄\書名.類型。 還需要在settings.py中定義下載后保存的路徑
# 保存書籍的路徑
FILES_STORE='./books'
定義自定義下載的管道
ITEM_PIPELINES = {
"getbooks.pipelines.KgBookFilePipeline": 300,
}
加入以下定義,強制爬取、下載,并忽略301,302重定向
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
MEDIA_ALLOW_REDIRECTS = True
HTTPERROR_ALLOWED_CODES = [301,302]
至此,就通過Scrapy爬蟲框架實現(xiàn)了一個爬蟲。 運行效果 執(zhí)行 scrapy crawl getkgbook -o books.json 可以看到控制臺打印出來的日志,爬蟲開始默默的勤勤懇懇的爬取了。
爬取的結(jié)果保存到了books.json中
要下載的書籍也保存到了books下相應(yīng)的目錄下了
三、注意事項
有可能在文件下載的時候并沒有把文件下載下來,原因是文件下載路徑有重定向。
2023-09-12 22:25:38 [scrapy.core.engine] DEBUG: Crawled (301)
2023-09-12 22:25:38 [scrapy.pipelines.files] WARNING: File (code: 301): Error downloading file from
2023-09-12 22:25:38 [scrapy.core.engine] DEBUG: Crawled (301)
2023-09-12 22:25:38 [scrapy.pipelines.files] WARNING: File (code: 301): Error downloading file from
需要在settings.py中加入
MEDIA_ALLOW_REDIRECTS = True #直接下載
HTTPERROR_ALLOWED_CODES = [301,302] #忽略重定向的報錯信息
現(xiàn)在我們通過一個Scrapy爬蟲框架實例實現(xiàn)了網(wǎng)站的爬取,重代碼量上看比python直接寫少了很多,通用性也更強了。通過管道不僅僅可以將數(shù)據(jù)保持至json還可以保存到Excel、數(shù)據(jù)庫等。
博客地址:http://xiejava.ishareread.com/
柚子快報邀請碼778899分享:Scrapy爬蟲框架實戰(zhàn)
精彩鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。