新手學習爬蟲之建立第一個完整的scrapy工程-糗事百科
建立第一個scrapy工程-糗事百科
最近不少小夥伴兒,問我關於scrapy如何設定headers的問題,時間久了不怎麼用,還真有的忘,全靠記憶去寫了,為了方便大家參考,也方便我以後的查閱,這篇文章就誕生了。本章內容從實戰出發讓我們熟悉如何用scrapy寫爬蟲,本篇內容主要是實戰,不講述過多的理論性東西,因為講多了我也不知道。?
明確目標
首先,我們要明確我們的爬蟲最終的目的是什麼,這裡我們要做的是爬取糗事百科的熱門分類的前10頁資訊。包括髮布者和內容,因為入門教程所以我們寫的簡單點主要是熟悉這個過程,這個如何入手呢?
分析連結的變化
一般我們會通過點選下一頁,然後觀察位址列的資訊來總結規律。第一頁也就是首頁地址為:https://www.qiushibaike.com/我們點選下一頁可以發現第二頁的的連線為:https://www.qiushibaike.com/8hr/page/2/第三頁:https://www.qiushibaike.com/8hr/page/3/。。。以此類推第十頁的連線為:https://www.qiushibaike.com/8hr/page/10/由此我們發現規律,從第二頁開始連線可以用https://www.qiushibaike.com/8hr/page/頁數/來表示,有時候我比較喜歡試探,怎麼說呢,我們知道這個規律是從第二頁開始的,但是第一頁是沒有這個規律,但是我們不防試一試把第一頁的https://www.qiushibaike.com/改為https://www.qiushibaike.com/8hr/page/1/。然後我們訪問看看ok可以正常顯示。
安裝scrapy
我們要確保正確安裝好了scrapy針對mac和linux直接執行pip安裝即可。
pip install scrapy
但是windows的坑就比較多了,關於windows的安裝請參考我之前寫的這篇文章:https://www.cnblogs.com/c-x-a/p/8996716.html。這裡就不多說了。
建立scrapy工程
好了下面我們開始建立工程首先我們使用scrapy的第一個命令startproject,使用方法:scrapy startproject xxx xxx就是你的專案名,這裡我們給我們的專案起名qiushibaile。
scrapy startproject qiushibaike
然後我們會發現了多了一個檔名為qiushibaike的資料夾然後我們通過命令建立一個事例工程進入qiushibaikle
cd qiushibaike
然後用下面scrapy的第二個命令genspider使用方法 scrapy genspider spider_name domainspider_name就是爬蟲的名字,每一個爬蟲有一個名字這個名字是唯一的,後面執行的時候也是通過這個名字來執行的,下面的qsbk就是我們的爬蟲名字,domain指定爬蟲的域也就是爬蟲的範圍。查詢網頁我們發現域名為
scrapy genspider qsbk qiushibaike.com
看到以下命令證明我們成功的建立了專案。
Created spider 'qsbk' using template 'basic' in module: qiushibaike.spiders.qsbk
開始編寫spider檔案
我們這裡使用pycharm把我們的爬蟲工程載入進來。目錄結構如下
(注意:run.py是我後期自己新增的一個爬蟲入口檔案)修改settings.py檔案
無視robots協議,將
ROBOTSTXT_OBEY = True
改為
ROBOTSTXT_OBEY = False
修改spider.py
我們先來看看我們訪問的網頁原始碼對不對。把qsbk.py 改為
# -*- coding: utf-8 -*-import scrapyclass QsbkSpider(scrapy.Spider): name = 'qsbk' allowed_domains = ['qiushibaike.com'] start_urls = ['http://qiushibaike.com/']#種子url,列表型別表示支援多個 def parse(self, response): print(response.text)#輸出原始碼
建立入口檔案執行
在專案的根目錄下建立一個run.py 來執行我們的工程run.py的內容如下
# -*- coding: utf-8 -*-# @Time : 2018/10/31 11:54 PM# @Author : cxa# @File : run.py.py# @Software: PyCharmfrom scrapy.cmdline import executeexecute(['scrapy','crawl','qsbk'])
執行以後我們發現一堆紅色的資訊,這些都是scrapy 的日誌內容,我們注意找是否有黑色字型的內容,一般print出來的內容是黑色字型和含有error的資訊,以此瞭解我們的爬蟲哪個地方出錯了,
我們找到了error關鍵字,可以得知我們的爬蟲出錯了2018-11-01 00:08:38 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET https://www.qiushibaike.com/> (failed 1 times): [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed cleanly.>]2018-11-01 00:08:38 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET https://www.qiushibaike.com/> (failed 2 times): [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed cleanly.>]2018-11-01 00:08:38 [scrapy.downloadermiddlewares.retry] DEBUG: Gave up retrying <GET https://www.qiushibaike.com/> (failed 3 times): [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed cleanly.>]2018-11-01 00:08:39 [scrapy.core.scraper] ERROR: Error downloading <GET https://www.qiushibaike.com/>Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/scrapy/core/downloader/middleware.py", line 43, in process_request defer.returnValue((yield download_func(request=request,spider=spider)))twisted.web._newclient.ResponseNeverReceived: [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed \
按照提示可以知道連結被關閉訪問失敗了,這種情況下我們就被反爬了,常見的應對措施是修改headers頭,下面我們就通過修改中介軟體來修改headers。
修改中介軟體加入headers資訊
首先修改middlewares.py
class UserAgentMiddleware(object): def __init__(self, user_agent_list): self.user_agent = user_agent_list @classmethod def from_crawler(cls, crawler, *args, **kwargs): # 獲取配置檔案中的MY_USER_AGENT欄位 middleware = cls(crawler.settings.get('MY_USER_AGENT')) return middleware def process_request(self, request, spider): # 隨機選擇一個user-agent request.headers['user-agent'] = random.choice(self.user_agent)
然後在settings啟用我們的中介軟體和設定MY_USER_AGENT的值:
MY_USER_AGENT = ["Mozilla/5.0+(Windows+NT+6.2;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36", "Mozilla/5.0+(Windows+NT+5.1)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/28.0.1500.95+Safari/537.36+SE+2.X+MetaSr+1.0", "Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/50.0.2657.3+Safari/537.36"]DOWNLOADER_MIDDLEWARES = { 'qiushibaike.middlewares.UserAgentMiddleware': 543,}
然後我們再次執行,run.py檔案。
再次執行
我們成功獲取了原始碼,
。然後我們就需要進行解析內容了。解析網頁中所需要的內容
因為這10頁的結構是類似的我們就拿第一頁為例:在這裡我們使用的解析方法為xpath,通過xpath可以解析出我們需要的內容,開啟谷歌瀏覽器的開發者工具,首先通過Elements模組獲取當前頁所有內容的大概區域我們可以寫這樣的一個xpath。
"//div[@id='content-left']"
然後我們發現一頁25個內容,然後再去在每個內容裡進行查詢當前的標題和內容。在qsbk.py檔案的parse方法里加入這段內容
content_left_node=response.xpath("//div[@id='content-left']") #確定釋出區的節點區域 div_node_list=content_left_node.xpath("./div") for div_node in div_node_list: title_node=div_node.xpath(".//div[@class='author clearfix']/a[contains(@onclick,'web-list-author-text')]/h2/text()") content_node=div_node.xpath(".//div[@class='content']/span[1]") content=content_node.xpath('string(.)') print("釋出者",title_node.extract_first().strip()) print("釋出內容",content.extract_first().strip())
修改scrapy的日誌顯示等級方便檢視
前面執行過程中我們發現scrapy的日誌資訊非常的多,不容易找到我們想要的內容,這個時候我們可以通過修改settings.py檔案通過修改log的等級,只顯示指定型別的log,開啟settings.py我們加上下面的一句來設定log的等級為error也就是隻有錯誤的時候才顯示scrapy的log資訊。
LOG_LEVEL = "ERROR"
然後再次執行,看到了我們我們需要的內容釋出者和釋出內容。得到了這些我們現在只是列印了下,下面我們就來說如何儲存
儲存結果到mongodb
mongodb是一個key-value型的資料庫,使用起來簡單,資料結構是鍵值對型別,在儲存過程中如果表不存在就會建立一個新的表。下面我們開始來儲存我們的資料。
構造資料
因為我們需要接收一個鍵值對型別的資料,一般用dict,所以我們將程式碼改成如下形式。qsbk.py檔案新增內容:
item = {} item['name'] = name item['info'] = info yield item
上面我們構造出了我們需要儲存的資料,然後通過yield傳遞到儲存部分,下一步我們就要開始建立mongo連線的部分了。
建立mongo連線檔案
把pipelines.py 檔案改為
import pymongofrom scrapy.conf import settingsclass MongoPipeline(object): def __init__(self): # 連結資料庫 self.client = pymongo.MongoClient(host=settings['MONGO_HOST'], port=settings['MONGO_PORT']) if settings.get('MINGO_USER'): self.client.admin.authenticate(settings['MINGO_USER'], settings['MONGO_PSW']) self.db = self.client[settings['MONGO_DB']] # 獲得資料庫 self.coll = self.db[settings['MONGO_COLL']] # 獲得collection def process_item(self, item, spider): postItem = dict(item) # 把item轉化成字典形式 self.coll.insert(postItem) # 向資料庫插入一條記錄 return item
然後修改settings.py,首先新增mongo的幾個連線引數
MONGO_HOST = "127.0.0.1" # 主機IPMONGO_PORT = 27017 # 埠號MONGO_DB = "spider_data" # 庫名MONGO_COLL = "qsbk" # collection名
然後開啟pipe通道
ITEM_PIPELINES = { 'qiushibaike.pipelines.MongoPipeline': 300,}
執行檢視資料
我這裡用的adminmongo,開啟adminmogo連線資料庫,可以看到我們資料已經存在了。
結語
到此為止,我們一個簡單完整的scrapy小專案就完成了。 為了方便檢視程式碼已經上傳git:https://github.com/muzico425/qsbk.git更多爬蟲學習以及python技巧,請關注公眾號:python學習開發。