1. 程式人生 > >新手學習爬蟲之建立第一個完整的scrapy工程-糗事百科

新手學習爬蟲之建立第一個完整的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可以正常顯示。

於是我們就確定了連結,也就是頁數改為1-10就可以訪問相應的頁數了。

安裝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.retryDEBUG: 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.retryDEBUG: 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.retryDEBUG: 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 43in 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學習開發。