最近很多小夥伴兒,問我關於scrapy如何設置headers的問題,時間久了不怎麼用,還真有的忘,全靠記憶去寫了,爲了方便你們參考,也方便我之後的查閱,這篇文章就誕生了。本章內容從實戰出發讓咱們熟悉如何用scrapy寫爬蟲,本篇內容主要是實戰,不講述過多的理論性東西,由於講多了我也不知道。😄
html
首先,咱們要明確咱們的爬蟲最終的目的是什麼,這裏咱們要作的是爬取糗事百科的熱門分類的前10頁信息。包括髮布者和內容,由於入門教程因此咱們寫的簡單點主要是熟悉這個過程,這個如何入手呢?node
通常咱們會經過點擊下一頁,而後觀察地址欄的信息來總結規律。
第一頁也就是首頁地址爲: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能夠正常顯示。
python
咱們要確保正確安裝好了scrapy
針對mac和linux直接運行pip安裝便可。linux
pip install scrapy複製代碼
可是windows的坑就比較多了,關於windows的安裝請參考我以前寫的這篇文章
:https://www.cnblogs.com/c-x-a/p/8996716.html。這裏就很少說了。git
好了下面咱們開始建立工程首先咱們使用scrapy的第一個命令startproject,
使用方法:scrapy startproject xxx xxx就是你的項目名,這裏咱們給咱們的項目起名qiushibaile。github
scrapy startproject qiushibaike複製代碼
cd qiushibaike複製代碼
而後用下面scrapy的第二個命令genspider
使用方法 scrapy genspider spider_name domain
spider_name就是爬蟲的名字,每個爬蟲有一個名字這個名字是惟一的,後面運行的時候也是經過這個名字來運行的,下面的qsbk就是咱們的爬蟲名字,domain指定爬蟲的域也就是爬蟲的範圍。查找網頁咱們發現域名爲web
scrapy genspider qsbk qiushibaike.com複製代碼
看到如下命令證實咱們成功的建立了項目。mongodb
Created spider 'qsbk' using template 'basic' in module: qiushibaike.spiders.qsbk複製代碼
咱們這裏使用pycharm把咱們的爬蟲工程加載進來。
目錄結構以下
數據庫
無視robots協議,將windows
ROBOTSTXT_OBEY = True複製代碼
改成
ROBOTSTXT_OBEY = False複製代碼
咱們先來看看咱們訪問的網頁源碼對不對。
把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的信息,以此瞭解咱們的爬蟲哪一個地方出錯了,
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。
首先修改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的日誌信息很是的多,不容易找到咱們想要的內容,這個時候咱們能夠經過修改settings.py文件經過修改log的等級,只顯示指定類型的log,打開settings.py咱們加上下面的一句來設定log的等級爲error
也就是隻有錯誤的時候才顯示scrapy的log信息。
LOG_LEVEL = "ERROR"複製代碼
而後再次運行,看到了咱們咱們須要的內容發佈者和發佈內容。
獲得了這些咱們如今只是打印了下,下面咱們就來講如何存儲
mongodb是一個key-value型的數據庫,使用起來簡單,數據結構是鍵值對類型,在存儲過程當中若是表不存在就會建立一個新的表。
下面咱們開始來存儲咱們的數據。
由於咱們須要接收一個鍵值對類型的數據,通常用dict,因此咱們將代碼改爲以下形式。qsbk.py文件新增內容:
item = {} item['name'] = name item['info'] = info yield item複製代碼
上面咱們構造出了咱們須要存儲的數據,而後經過yield傳遞到存儲部分,
下一步咱們就要開始建立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學習開發。