10分鐘教你Python爬蟲(下)–爬蟲的基本模組與簡單的實戰
- 2020 年 2 月 25 日
- 筆記
新年快樂
各位看客老爺們,新年好。小瑋又來啦。這次給大家帶來的是爬蟲系列的第二課—爬蟲的基本模組與簡單的實戰。
說到爬蟲的基本模組,不知道大家之前有沒有了解過呢。如果你之前沒有了解過,給小瑋一個機會帶您慢慢了解它,如果你之前了解過,也請給小瑋一個機會幫助您再次鞏固。
下面讓我來慢慢細說。

在這節課上,我們會主要了解兩個模組,requests和BeautifulSoup。
在最開始呢,肯定是大家要下載安裝一下這兩個模組。當然如果你按照很久以前的一篇推文裡面安裝的是anaconda的話,你就不需要下載,因為早就已經安裝好了。
下面我介紹一下直接安裝python的人的安裝方法。打開cmd控制台,輸入pip install requests,mac用戶呢,輸入pip3 install requests等待下載結束就可以了。Beautifulsoup的安裝會在後面給出。
下面分別來介紹一下這兩個模組。requests是幹什麼用的呢。它是用作進行網路請求的模組。在這裡給大家舉一個例子,大家可以試著去輸出一下下面的程式碼,看看到底是什麼。
import requests req=requests.get('http://docs.python-requests.org/en/master') print(type(req)) print(req.status_code) print(req.encoding) print(req.cookies)
這裡的status是狀態碼,encoding是編碼方式。在這裡簡單的介紹一下常見的狀態碼。

那麼最後的cookies是啥呢?
其實就是一個記錄你在這個網頁中的活動的東西,可能這麼說並不是很形象,可以這樣理解,在抖音等APP上,你有沒有發現經常看的一些種類的影片總是不斷的推送給你,而其他的內容很少推送給你,這是為什麼呢?原因很簡單,就是因為有這個cookies記錄了你的愛好。
就我個人而言,並不是很喜歡cookies,因為有可能你無意中點到了某個東西,她就不斷地給你推送。考慮到有些人會和小編一樣不太習慣一些莫名其妙的推送,一些網站會詢問用戶是否同意網站有cookies。
對於requests其實介紹到這裡就差不多了,因為還有其他的內容在我們的課上不會用到很多。如果大家還有別的需求的話,可以去網上搜一搜。那麼下面我們介紹一下BeautifulSoup。
對於這個模組,我想說她確實是一個爬蟲利器,出色的解析工具。因為我們直接用requests獲取這個網頁程式碼的時候,我們的程式是不知道究竟這個程式碼中有些什麼東西的,只有通過解析html程式碼我們才知道這個網頁中究竟有一些什麼。
BeautifulSoup 的安裝比requests的安裝會複雜一點,她需要安裝兩個東西。一個是lxml,一個是beautifulsoup4,打開cmd命令行,輸入pip install lxml,輸入pip install beautifulsoup4就可以了。
在導入這個模組的時候,我們通常是這樣進行導入的。
from bs4 import BeautifulSoup
這個模組怎麼使用呢?在這裡舉一個例子,大家可以去嘗試一下。
import requests from bs4 import beautifulsoup r=requests.get(網址) html=r.text soup=Beautifulsoup(html,』lxml』) print(soup.prettify())
把這個程式的網址位置填上相應的網址就可以進行輸出了。最後的prettify函數是做什麼的呢?他是用來把我們輸出的內容進行一定的格式化,相當於美化一樣的作用。
不知道大家在上一節課的時候是否還記得標籤Tag這個屬性。
現在這個屬性就起作用啦。因為現在我們的soup已經把整個網頁源程式碼進行了解析,那麼接下來我們就可以通過soup.tag來輸出我們需要的內容。比方說我想要輸出我們當前網頁的title,我們就可以print(soup.title)就可以輸出了,十分簡單。
當然這個輸出並不是把所有這個標籤的量都返回,她只會返回第一個帶有這個標籤的量。如果想要獲得所有的這類標籤的內容,就可以使用soup.find_all(『xxx』),就可以找到所有這個標籤的內容。
差不多把基礎內容說了一下之後呢,現在讓我們進入實戰的環節。今天我們爬取的內容是一個叫做笑話大全zol的網站。
首先,在最開始,我們應該要做的是引用模組
import requests from bs4 import beautifulsoup
然後找到咱們瀏覽器的header,header怎麼找我就不再多說了啊,在之前的推文已經說過了,這裡就不重複說了。寫上
header={'User-Agent':xxxxxx}
然後讓我們進入http://xiaohua.zol.com.cn/這個網址。如果你有電腦在身邊的話,可以現在就打開這個網址進入。

進入了以後,隨便點擊一個分類,在本次教學中我們點擊的是冷笑話這個分類。好的,點進來以後,我們先嘗試著對這個網頁進行一些爬取操作。
存放咱們的
url=http://xiaohua.zol.com.cn/lengxiaohua/,
然後用requests工具對這個網站進行請求。
html=requests.get(url,headers=heades)
然後對這個網頁進行解析,
soup=BeautifulSoup(html,'lxml')
其實這個步驟在之前也已經仔細的說過了,在這裡沒有重複的必要,如果你仍然感到一些困惑,可以回到之前的推文再回顧一下。
這一次爬取的網頁比上一次爬取時間和距離的網頁更複雜,所以相關的操作也會更加麻煩。
讓我們繼續往下面看。我們現在已經完成了獲取網站源程式碼並進行解析的過程了,接下來我們就要確定我們所需要爬取的內容。
觀察這個頁面,找出我們所需要內容所在的最小單元。仔細觀察了以後,我們可以知道,我們需要的最小單元是這樣一塊內容。

現在已經明確了我們需要爬取每一個這樣的方塊裡面的相應內容以後,我們要做的就是找到這一塊東西的位置的源程式碼。右鍵點擊空白處,選擇檢查。出現如圖所示的介面。

大家肯定會問,打開這個做什麼呢?
這個是幫助我們確定我們到時候需要爬取的內容的標籤是什麼。點擊左上角的箭頭符號,放在我們選取的最小單元上面,我們可以看到如圖所示的東西。

這個時候我們就可以發現,其實每一個這樣的最小單元對應一個article-summary這個標籤。
這樣就很明確了,我們所需要的內容就在每一個article-summary裡面。我們利用beautifulsoup的特有函數select選擇器函數選定這個內容,lis=soup.select(.article-summary),記住一定要在article-summary前面加上『.』,這是因為雖然select選擇器中可以不寫class,但是你必須指明我們需要的內容是一個class,怎麼指明呢?就是通過這樣一個『.』符號。
現在為止,我們已經獲取了所有的article-summary,並且存到了lis裡面.
當然還不夠,我們需要的東西並不是lis裡面所有的東西,就打個比方說,這次爬取我的主要目的是笑話標題,笑話內容和笑話來源。那麼我就需要再回到檢查頁面,找到我們所需要內容的標籤。
下面是標題的標籤。

下面是來源的標籤。

下面是內容的標籤。

在很多時候,可能你不知道自己標籤選擇正確沒有,我們可以在檢查欄,按下ctrl+f,出現搜索欄,輸入我們當前的標籤。
如圖所示,既可以幫助我們檢查標籤查找是否正確,同時有利於我們估計網頁中符合條件的項目數量。

現在已經把目標的標籤找到了以後,我們就可以把內容賦給相應的變數。如下
title=li.select_one('.article-title a').text source=li.select('.article-source')[1].text content=li.select('.summary-text p') laugh='' for c in content: laugh=laugh+c.text
在這裡我們講解一下程式碼,為什麼第一行我們要使用select_one呢?這是一個li標籤中只有一個title,我們只需要選擇這一個就可以了,即選擇第一個。
.text的作用重新再說一下,因為我們在獲取這個標籤下的東西的時候,其實是有很多東西的,還有各種各樣的標籤,當然標籤我們是不要的,怎麼辦呢?使用.text就可以了。
第二行的程式碼,我們在後面加了一個[1],這是為什麼呢?因為我們看上面的搜索結果,其實這個標籤裡面的內容有兩個,第一個是『來源:』,第二個才是我們要的內容,因為index是從0開始的,所以我們選擇的是[1]。
但是我們還需要進行一些別的操作,我們這樣做只是把一個最小單元裡面的內容存進去了,並不是所有的。那如果我們想要把所有的單元都存進去呢?這個也很簡單,利用for函數就可以輕鬆實現。
for li in lis:
這個函數的意思就是依次把lis裡面的內容取出來賦給li。
其實到這個位置,我們已經完成了當前頁面的爬取,各位看客老爺們可以試著輸出一下我們這幾個變數,看看是不是爬取成功。那麼請在保證上面內容已經完成的前提下,我們繼續下面的內容。
因為是爬取內容嘛,我們當然不會只爬這一個頁面,這肯定是遠遠不夠的。那麼怎麼辦呢?我們怎麼才能爬取多個頁面呢?
對,沒錯,就是不斷的進行換頁操作就可以了。那麼怎麼進行換頁呢?這就需要我們觀察頁面的規律了,下面我們一起來探究一下我們正在爬取的網址的規律。
http://xiaohua.zol.com.cn/lengxiaohua/2.html http://xiaohua.zol.com.cn/lengxiaohua/3.html ……
其實這個網頁是相當有規律的,我們可以很輕鬆發現他這個網址其實就是
http://xiaohua.zol.com.cn/lengxiaohua/{}.html
這樣子,對吧?這樣我們是不是就可以用到for函數和format()函數來進行我們的翻頁操作了?是的!讓我們看一看程式碼。
for i in range(1,10)#這裡的意思是生成1-9的整數,在這裡我們假設爬取1-9面的內容 for i in range(1,5): url='http://xiaohua.zol.com.cn/lengxiaohua/{}.html'.format(str(i))
在這裡一定要注意,要用強制轉換str(),為什麼呢?這是因為我們網址裡面的數字類型其實是字元串型的。
現在我們已經完成了翻頁功能,也完成了相應頁面的爬取功能,但是還是不夠完美。主要還有以下幾個問題.
是不是最終輸出的結果有很多空白?有很多其他字元?是不是來源那個位置有的時候會出錯?
別急,我們一個一個來解決。為了使我們的輸出結果更加精簡和規範。我們可以使用strip函數和replace函數。
strip() 方法用於移除字元串頭尾指定的字元(默認為空格或換行符)或字元序列。replace()函數用於去除其他位置的空白。讓我們在程式碼裡面看看具體怎麼寫。
laugh=laugh.strip().replace(' ','')#strip()刪除開頭和結尾的字元
replace函數的使用方式是replace(a,b),意思是把文本中的a用b代替。解決了這個問題之後,我們來解決來源出錯的問題。
我們來分析一下為什麼有的時候來源這個位置會出錯,我們回到原來的頁面觀察來源那個位置,我們可以看到有很多笑話都是沒有來源的,那麼這個時候我們其實啥都沒有爬取到,所有就會出錯。
那麼這個時候怎麼辦呢?我們只需要進行一個簡單的判斷。
try: source=li.select('.article-source')[1].text except: source='暫無來源'
這是什麼意思呢?意思就是如果try裡面的內容沒有出錯,我們就執行try裡面的內容,如果出錯了,我們就執行except裡面的內容。
但是到目前為止,我們還是有問題的,雖然我們已經完成了整個的爬取,但是我們還沒有把他們存進來呀。如果我們要存進來怎麼辦呢?這就涉及到python的文件操作了。在這裡呢,小瑋就不多說文件的操作了。大家看看程式碼應該可以明白的!
下面給出所有的程式碼。
import requests from bs4 import BeautifulSoup headers={"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.116 Safari/537.36"} for i in range(1,5): fw = open('./record{}.txt'.format(i),'w',encoding='UTF-8') fw.write('page{}n'.format(i)) print('page{}'.format(i)) url='http://xiaohua.zol.com.cn/lengxiaohua/{}.html'.format(str(i)) html=requests.get(url,headers=headers) soup=BeautifulSoup(html.text,"lxml") lis=soup.select('.article-summary') for li in lis: title=li.select_one('.article-title a').text try: source=li.select('.article-source')[1].text except: source='暫無來源' content=li.select('.summary-text p') laugh='' for c in content: laugh=laugh+c.text laugh=laugh.strip().replace(' ','')#strip()刪除開頭和結尾的字元 print(title,source) print(laugh) print('-'*30) fw.write('title:{}nsource:{}nlaugh:{}n'.format(title,source,laugh)) fw.write('-'*30+'n') fw.close()
其實到目前位置,做一個比較簡單的爬蟲項目已經足夠了,但是我們會在後面介紹更加專業適用於大項目的爬蟲方法,讓我們一起期待下一期推文吧!