【Python實戰】手把手超詳細教程教你Scrapy爬達蓋爾社區,有彩蛋

發出前兩篇Python實戰的文章以後,有同窗和我反映:你的想法很牛逼,但是我就是看不懂你寫的是什麼,我Python不熟悉,看起來有點吃力。我細細一琢磨,這點是個問題。對於熟悉Python的同窗,可以看懂我思路,可是對於那些沒有Python基礎,或者對Python不熟悉的同窗,這樣直接扔過來,可能會讓他們失望而歸。因此,這回我弄了一期手把手的實戰教程,同時,在文章中遇到的知識點,還會有提供連接。徹底對新手有好。css

在前兩篇Python實戰「用代碼來訪問1024網站」「用Scrapy編寫「1024網站種子吞噬爬蟲」」收到了你們的一致好評,可能文章寫得比較匆忙,有些術語可能對於Python的初級玩家不是很好理解。因此,我特別準備了一下,用超級詳細的解說,細化到每一步,提供查詢連接等方法,爲Python初級玩家,Python小白和對Scrapy框架不熟悉的同窗,的製做了這篇手把手Python實戰教程:用Scrapy爬取下載達蓋爾社區的資源。html

好了,廢話很少說,學習代碼就是要學以至用的。不能寫了一遍代碼就讓代碼吃灰。下面就跟我一塊兒來搞吧。數據庫

小草網站是個好網站,咱們此次實戰的結果,是要把「達蓋爾旗幟」裏面的帖子爬取下來,將帖子的圖片保存到本地,同時將帖子的一些相關信息,寫入到本地的MongoDB中。這麼乍一聽,感受咱們作的事情好像挺多的,別慌,我帶你慢慢的一步一步來搞起,問題不是很大。編程

手把手 Step By Stefp

Scrapy能夠經過pip來安裝:bash

$ pip install scrapy
複製代碼

接下來,咱們去事先建好的工程目錄裏面,建立Scrapy的項目。這裏,咱們先看一下Scrapy的命令行怎麼用,輸入$ scray -help出來框架

scrapy幫助文檔

看到,建立scrapy的工程的命令是$ scrapy startproject <name>建立完的結果以下:dom

建立工程成功

OK,這個時候,咱們的目錄內容變成了以下結構:scrapy

工程結構目錄

下一步就是建立咱們的爬蟲,仍是依靠Scrapy自己自帶的命令來建立。輸入Scrapy自帶四種爬蟲模板:basiccrawlcsvfeedxmlfeed四種。咱們這裏選擇basic。ide

$ scrapy genspider --template=basic superspider bc.ghuws.men
複製代碼

建立成功,會出現如下提示:函數

建立爬蟲

這時候咱們的工程目錄就變成了這個樣子:

有了爬蟲的工程目錄

看到咱們的工程裏面多了一個spiders文件夾,裏面有一個superspider.py文件,這個就是咱們此次程序的主角。咱們來看,這個可愛的小蟲子剛生下來是長這個樣子的:

爬蟲

這裏呢,就簡單說一下:

  • name - 是我們的爬蟲名字,這個主要是在運行爬蟲的時候會用到。
  • allowed_domains - 是在scrapy自帶的OffsiteMiddleware中用到的。Scrapy默認會開啓OffsiteMiddleware插件,不在此容許範圍內的域名就會被過濾,而不會進行爬取。
  • start_urls - 爬蟲開始爬取的url。
  • parse()方法 - 這個就是處理請求結果的。咱們具體的爬蟲邏輯大部分就是在這裏寫。

好了,廢話很少說,既然start_urls是用來作爬蟲開始爬取的第一個url,那麼咱們就應該把這裏面的數值換成達蓋爾社區的地址,而後咱們看一下在parse()裏面返回的值是什麼。運行方法,就是輸入$ scrapy crawl superspider指令便可:

爬蟲v0.1

response對象

response對象的body

咱們看到,這個response是一個HtmlResponse類,它裏面的text屬性,裏面的字符串就是網頁的html文件。OK,這一步結束以後,咱們下一步就想辦法怎樣可以解析html網頁了。Scrapy是提供了html對象的解析的,它有一個selector類,能夠解析html,同時,裏面還支持xpath語法的查找和css的查找。可是這個我的感受不是很好用,我推薦用BeautifulSoup4庫。安裝方法只須要$ pip install beautifulsoup4。咱們這裏須要用這個來解析html,因此講BeautifulSoup4導進來,在解析,而後咱們就會獲得一個beasutifulsoup對象。以後,咱們就要在這個對象裏面尋找咱們須要解析的對象。

BeautifulSoup的對象

bs解析

目前網頁已經解析好了,下一步就是要在html文件中,找到每個帖子的信息。咱們回頭來看html文件的源碼,能夠看到,每個帖子其實都是在一個<tr>tag裏面,其實咱們須要的東西,就是下圖紅色框框裏面圈的<a>tag。

html頁面

這裏,咱們發現,每個帖子的連接入口,也就是<a>tag是有兩個特性,一個是有id值,另外一個是有href值。因此,咱們要針對soup對象,調用find_all()方法來尋找有特定內容的全部標籤。

抓取全部的 a 標籤

a 標籤結果

咱們獲得了一個 a_list結果,這是一個list對象,長度102。在這些數據中,有些結果是咱們不要的,好比000到007位置的這幾個數據,他們在網頁中對應的是版規之類的帖子信息,和咱們想要的東西不同,因此,在拿到這個a_list數據,咱們須要進行一下篩選。

篩選的過程必不可少,篩選的方法有不少種,咱們這裏就作的簡單一點,只選取18年的帖子。爲何會是18年的帖子啊?少年你看,這一列href的值:

href的區別

第二個數字「1805」,應該就是「年份+月份」。若是不信,則能夠跳到好比論壇100頁,看到的是16年3月份的帖子,這裏面隨便檢查一個鏈接的href值,是「1603」。這就印證了咱們的想法是正確的。好,按照這個篩選18年的帖子的思路,咱們來篩選一下a_list

篩選結果diamante

篩選完的結果

看到打印的結果倒是是18年的帖子。可是目前的href並非帖子真正的url。真正的url應該長這個樣子:

http://bc.ghuws.men/htm_data/16/1805/3126577.html
複製代碼

因此,咱們這裏得進行拼接。對比上面的url,咱們目前只有後半部分,前半部分實際上是社區網站的root url。那麼咱們在settings.py文件裏面添加一個ROOT_URL變量,並將這個變量導入到咱們的spider中便可。代碼就變成了這樣。爲了方便,我們還能夠把帖子的id,也就是.html前面的那個數字也摘出來,方便往後使用。

拼湊出帖子地址

目前爲止,咱們拿到了帖子的id和帖子的url。咱們的最終目的是要下載圖片,因此,咱們得讓爬蟲去按照帖子的url去爬取他們。爬蟲須要進入第二層。這裏,咱們須要使用yield函數,調用scrapy.Request方法,傳入一個callback,在callback中作解析。

二級爬蟲

如今咱們已經進入了每個帖子的內部,咱們如今尚未拿到的信息有帖子的標題和帖子的圖片。仍是和parse()的步驟同樣,這個時候,咱們就該分析帖子的html文件了。
咱們先找標題。看到html文件中,標題對應的是一個<h4>標籤。

post的html

那這就簡單了,咱們只須要找到全部的<h4>標籤,而後看標題是第幾個就好。接下來是圖片了。每一個帖子用的圖牀都不同,因此圖片部分,咱們先來看一下結構:

圖片的標籤1

圖片的標籤2

大概就是這兩種,咱們看到,圖片的標籤是<input>,關鍵點就在type=image上面,因此咱們嘗試着看看能不能根據這個來找到圖片的地址。

二級爬蟲完成

咱們簡單測試一下,看看運行效果:

爬取帖子頁面的圖片運行效果

徹底沒有問題,看着好爽。這時候,咱們看結果,會發現,咱們抓取到的image,會有一兩個的圖牀是不同的。

運行結果(部分)

打開也會看到這個圖片,裏面的內容也和其餘的圖片不同,而且這個圖片不是咱們想要的。因此,這裏咱們得作一下過濾。我這裏的方法就是要從找到的image_list裏面,把少數圖牀不同的圖片url給過濾掉。通常看來,都是找到的第一個圖片不是咱們想要的,因此咱們這裏只是判斷一下第一個和第二個是否同樣就能夠。

篩選圖片

這樣打印出來的結果就沒有問題嘍。

哈哈,如今咱們已經拿到了帖子的id,標題,帖子的url地址,還有帖子裏面圖片的url地址。離咱們的目標又近了一步。我以前說過,咱們的目標是要把每張圖片都保存在本地,目前咱們只是拿到了每張圖片的url。因此,咱們須要把圖片都下載下載下來。

其實,當拿到圖片的URL進行訪問的時候,經過http返回的數據,雖然是字符串的格式,可是隻要將這些字符串保存成指定的圖片格式,咱們在本地就能夠按照圖片的解析來打開。這裏,咱們拿到帖子的image_list,就能夠在yield出一層請求,這就是爬蟲的第三層爬取了。

紅框框的很關鍵

同時,在第三層爬蟲裏面,咱們還須要將訪問回來的圖片保存到本地目錄。那麼代碼就長這個樣子:

三級爬蟲

在上面第二次爬取函數的最後,有個地方須要注意一下,就是上圖中紅色框框圈出來的地方。這裏須要加上dont_filter=True。不然就會被Scrapy給過濾掉。由於圖牀的地址,並未在咱們剛開始的allow_domain裏面。加上這個就能夠正常訪問了。

這樣運行一遍,咱們的本地目錄裏面就會有保存好的下載照片了。

圖片保存節選

本地文件夾保存的下載好的圖片

咱們還有個問題,就是咱們須要將每一個帖子的信息(id,title,url,image)都保存到本地的數據庫中。這個該怎麼作?

別慌,這個其實很簡單。

首先,咱們得針對每一個帖子,創建一個Scrapy的item。須要在items.py裏面編寫代碼:

scrapy item

寫好以後,咱們須要在爬蟲裏面引入這個類,在第二層解析函數中,構建好item,最後yield出來。這裏,yield出來,會交給Scrapy的pipeline來處理。

生成item

yield出來的item會進入到pipeline中。可是這裏有個前提,就是須要將pipeline在settings.py中設置。

將pipeline添加到settings裏面

pipeline中咱們先打印帖子的id,看看數據能不可以傳入到這裏

pipeline

運行:

pipeline完美運行

看到數據是徹底能夠過來的,並且在Scrapy的log中,會打印出來每個item裏面的信息。

咱們若是想把數據保存到MongoDB中,這個操做就應該是在pipeline中完成的。Scrapy之因此簡歷pipeline就是爲了針對每一個item,若是有特殊的處理,就應該在這裏完成。那麼,咱們應該首先導入pymongo庫。而後,咱們須要在pipeline的__init__()初始化進行鏈接數據庫的操做。總體完成以後,pipeline應該長這個樣子:

pipeline代碼

那麼咱們來測試一下數據是否可以存入到MongoDB中。首先,在terminal中,經過命令$ sudo mongod來啓動MongoDB。

啓動MondoDB

那麼運行一下,看一下效果:

MongoDB裏面保存的數據

能夠看到,左側,有名爲Daguerre的數據庫,裏面有名爲postTable的表,並且咱們的數據成功的寫入了數據庫中。數據的格式如圖所展現,和咱們預期的結果是同樣的。

目前爲止,咱們完成了:從一頁page中,得到全部帖子的url,而後進入每一個帖子,再在帖子中,爬取每一個帖子的圖片,下載保存到本地,同時把帖子的信息存儲到數據庫中。

可是,這裏你有沒有發現一個問題啊?咱們只爬取了第一頁的數據,那如何才能爬取第二頁,第三頁,第N頁的數據呢?

別慌,只須要簡單的加幾行代碼便可。在咱們的spider文件中的parse()方法地下,加一個調用本身的方法便可,只不過,傳入的url得是下一頁的url,因此,咱們這裏得拼湊出下一頁的url,而後再次調用parse()方法便可。這裏爲了不無限循環,咱們設定一個最大頁數MAX_PAGES爲3,即爬取前三頁的數據。

爬取下一個頁面

OK,這樣就完事兒了,這個達蓋爾旗幟的爬蟲就寫好了。咱們運行一下瞅瞅效果:

Boom,運行效果爆炸

是否是很是的酷炫?再來看看咱們的運行結果:

爬蟲運行結果1

爬蟲運行結果2

爬蟲運行結果3

只能說,戰果累累,有圖有真相。

其實,這個程序,能夠加入middleware,爲http請求提供一些Cookie和User-Agents來防止被網站封。同時,在settings.py文件中,咱們也能夠設置一下DOWNLOAD_DELAY來下降一下單個的訪問速度,和CONCURRENT_REQUESTS來提高一下訪問速度。

DOWNLOAD_DELAY

CONCURRENT_REQUESTS

就像以前EpicScrapy1024項目裏面同樣。喜歡的同窗,能夠去借鑑那個項目代碼,而後融會貫通,自成一派,爬遍天下網站,無敵是多麼的寂8 寞~~~~

好啦,能看到這裏說明少年你很用心,很辛苦,是一個可塑之才。

廢話不說,看到這裏是有獎勵的。關注「皮克啪的鏟屎官」,回覆「達蓋爾」,便可得到項目源碼和說明文檔。同時,能夠在下面的菜單中,找到「Python實戰」按鈕,可以查看以往文章,篇篇都很是精彩的哦~

扯扯皮,我以爲學習編程最大的動力就是愛好,其實幹什麼事情都是。愛好可以提供無線的動力,讓人元氣滿滿的往前衝刺。代碼就是要方便做者,方便你們。寫出來的代碼要有用處,並且不要吃灰。這樣的代碼纔是好代碼。歡迎你們關注個人公衆號,「皮克啪的鏟屎官」,以後我會退出Python數據分析的內容,可能會結合量化交易之類的東西。

最後,來貼一張達蓋爾的圖片,記念一下這位爲人類作出傑出貢獻的人。

達蓋爾本尊

推薦閱讀:

【Python實戰】用Scrapy編寫「1024網站種子吞噬爬蟲」,送福利
【Python實戰】用代碼來訪問1024網站,送福利

![關注公衆號「皮克啪的鏟屎官」,回覆「達蓋爾」就能夠得到驚喜](底部二維碼.png

)
相關文章
相關標籤/搜索