填坑計劃:scrapy
scrapy簡介
Scrapy是適用於Python的一個快速、高層次的屏幕抓取和web抓取框架,用於抓取web站點並從頁面中提取結構化的數據。Scrapy用途廣泛,可以用於數據挖掘、監測和自動化測試。
Scrapy吸引人的地方在於它是一個框架,任何人都可以根據需求方便的修改。它也提供了多種類型爬蟲的基類,如BaseSpider、sitemap爬蟲等,最新版本又提供了web2.0爬蟲的支持。
ScrapyDemo
-
安裝scrapy
pip3 install scrapy
-
創建scrapy項目
在項目目錄下:scrapy startproject ScrapyDemo
-
使用PyCharm打開項目
爲了操作方便,在項目根目錄下創建run.py,以用於後面的啓動和調試項目# -*- coding: utf-8 -*- # 啓動項目腳本 from scrapy.cmdline import execute # 創建爬蟲 execute('scrapy genspider qidian_bookinfo "book.qidian.com"'.split())
可以看到:使用scrapy.cmdline.execute方法執行命令行指令,需要使用split函數將指令分隔開
-
創建爬蟲
在項目目錄下執行指令scrapy genspider qidian_bookinfo "book.qidian.com"
創建一個爬蟲,爬取的範圍是起點小說網的book目錄,本次就先拿這個作爲實驗對象
-
創建item對象
在Items.py文件中,按照提示創建內容
我們計劃爬取某小說的題目、作者、宣傳語、簡介內容四個部分,因此要創建4個Itemimport scrapy class ScrapydemoItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() author = scrapy.Field() intro = scrapy.Field() entry = scrapy.Field()
-
編寫爬蟲文件qidian_bookinfo.py
# -*- coding: utf-8 -*- import scrapy from ScrapyDemo.items import ScrapydemoItem # 具體爬蟲文件 class QidianBookinfoSpider(scrapy.Spider): name = 'qidian_bookinfo' # 允許爬取的域名範圍 allowed_domains = ['book.qidian.com'] # 開始爬取url start_urls = ['https://book.qidian.com/info/1004990267/'] def parse(self, response): title = response.xpath('//div[@class="book-info "]//h1//em/text()').get() author = response.xpath('//div[@class="book-info "]//h1//span//a/text()').get() intro = response.xpath('//div[@class="book-info "]//p[@class="intro"]/text()').get() entry = response.xpath('//div[@class="book-intro"]//p/text()').get().strip() # 返回對象 item = ScrapydemoItem(title=title, author=author, intro=intro, entry=entry) # 生成item yield item
可以看到,這裏使用的xpath作爲選擇器,因此需要先了解xpath語法
xpath語法參考
其實理解起來比較容易,比如下面的xpath解析式://div[@class="book-info "]//h1//em/text()
解析的對象是class="book-info "的div的下面的h1,h1下面的em標籤中的文本內容,這個內容就是作品題目
注意: 這裏作者遇到了一個坑點(和程序無關),這個網站的info頁面book-info類的div標籤類是帶一個空格的,筆者一開始去掉了空格,結果什麼都爬不到、
[@class="book-info "] #字符串最後有個空格是故意加上的,不加空格爬取不到
-
使用pipline處理內容
在pipline.py文件中處理爬蟲返回的內容,這裏將獲得的四種信息轉換成json格式並且存儲到本地文件
使用了scrapy中專門輸出Json格式數據的JsonLinesItemExporter來輸出數據
from scrapy.exporters import JsonLinesItemExporter
class ScrapydemoPipeline:
def __init__(self):
self.fp = open("bookinfo.json", "wb")
# json文件輸出器
self.exporter = JsonLinesItemExporter(self.fp, ensure_ascii=False, encoding='utf-8')
def open_spider(self, spider):
self.exporter.start_exporting()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
def close_spider(self, spider):
self.fp.close()
self.exporter.finish_exporting()
print("結束")
- 配置settings.py
在我們寫好了所有內容之後,爬蟲需要進行配置才能運行
編輯settings.py,取消註釋並且配置一下內容:# 1. 關閉遵守robots協議 ROBOTSTXT_OBEY = False # 2. 僞裝身份 DEFAULT_REQUEST_HEADERS = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en', 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36' } # 3. 使用pipeline處理獲取數據 ITEM_PIPELINES = { 'ScrapyDemo.pipelines.ScrapydemoPipeline': 300, }
- 在run.py中運行如下內容,即可啓動爬蟲
#執行指令 execute('scrapy crawl qidian_bookinfo'.split())
- 檢查目錄下的bookinfo.json結果
使用JsonLinesItemExporter輸出的數據如果有多個會佔多行,每行是獨立的json數據{ "title": "穿越之皇帝成長計劃", "author": "奧特曼會寫字", "intro": "醒掌天下權,醉臥美人膝,五千年風華煙雨,是非成敗轉頭空!", "entry": "主角一朝穿越驚現成了即將登位的太子,治理自己的國家。尋找名妃,培養子女,爾虞我詐;發展國家,收錄名臣,秣馬厲兵。是後宮佳麗三千還是後宮佳麗三千;西楚霸王、蜀漢名將、水滸英雄,誰能助我一統天下;從三皇五帝到唐宗宋祖,雄霸天下亦或是兒女情長,收錄不盡的名臣美人,挑戰無限的激情國戰。" }
如果使用JsonItemExporter輸出數據,多行數據是裝在一個json列表裏的,只佔一行