本文由圖雀社群成員 燦若星空 寫作而成,歡迎加入圖雀社群,一起創作精彩的免費技術教程,予力程式設計行業發展。
如果您覺得我們寫得還不錯,記得 點贊 + 關注 + 評論 三連???,鼓勵我們寫出更好的教程?
發刊詞
這是一套基於實戰的系列教程,從最簡單的爬蟲程式開始,授人予漁,詳細剖析程式設計的思路,完整展現爬蟲是如何一步步除錯到最終完成。分享關於爬蟲的各種知識、技巧,旨在幫助大家認識爬蟲、設計爬蟲、使用爬蟲最後享受爬蟲帶給我們在工作和生活上的各種便利。
預備知識
- 基本的python程式設計知識
- 這裡使用 Python3 作為開發環境
- 同時具備基本的裝包知識
- 基本的網頁程式設計知識
- 初步瞭解HTTP協議
這是最簡單的計算機程式
說起爬蟲每個人都或多或少的聽過與之相關的內容,覺得它或高深、或有趣。作為一名寫程式碼四五年的初級碼農來看,爬蟲程式是計算機程式裡面最簡單也是最有趣的程式。只要會上網衝浪就有寫爬蟲程式的天賦。
爬蟲為什麼是蟲呢?因為蟲子的頭腦比較簡單,爬蟲程式也是 ++“一根筋”++ ,不需要諱莫如深的數學知識,也不用設計精巧的各類演算法。我們只需要用計算機能聽懂的“大白話”平鋪直敘就可以啦。
開發爬蟲的基本套路
一句話總結所有爬蟲程式的作用: 模擬人類上網的操作,以此來查詢、下載、儲存資料。 接下來我要以 男人圖這個網站為例,分享套路。
step 1: 開啟目標網址
此處強烈推薦Chrome
首先開啟這個網址:www.nanrentu.cc/sgtp/, 會看到以下介面
。現在我們只是用瀏覽器手動開啟了這個頁面,接下來我們要用程式碼,讓程式也開啟這個頁面。這就要分析一下瀏覽器是如何開啟這個頁面的了,請看簡易流程圖。
在python中,可以使用 requests 這一工具包來傳送HTTP請求。為了瞭解程式所“看到” 頁面是什麼樣子的,我們需要把程式所得到HTML檔案儲存到本地,然後再用瀏覽器開啟,就能和程式感同身受了。從而達到“人機合一”的境界。
光說不練假把式,讓我們馬上來新建一個 index.py
檔案,然後在其中編寫如下內容:
import requests
url = "https://www.nanrentu.cc/sgtp/"
response = requests.get(url)
if response.status_code == 200:
with open("result.html",'a',encoding="utf-8") as f:
f.write(response.text)
複製程式碼
在瀏覽器開啟寫入的HTML檔案是這樣的
這怎麼和在瀏覽器中看到的不一樣呢?
這個時候我就要亮出一件絕世寶貝————Chrome除錯臺(按F12)來給您分析一波了。
其實我們在瀏覽器中看到的頁面並不僅僅是HTML頁面,而是css、js、html以及各種媒體資源綜合在一起並有瀏覽器最終渲染而出頁面,紅框的部分,標出了在這個過程中所載入的各個資源。
當我們用程式去請求伺服器時,得到僅僅是HTML頁面,所以程式和我們所看到的頁面就大相徑庭了。不過沒關係HTML是主幹,抓住了主幹其他的只需要順藤摸瓜就可以了。
step2:找到目標資源
開啟這個網址以後,各位小仙女就可以各取所需咯,想體驗蕭亞軒的快樂嘛?那目標就是小鮮肉;饞彭于晏的那樣的身子了?那肌肉帥哥就是你的菜。此外韓國歐巴,歐美型男也是應有盡有。
人類是高階生物,眼睛會自動聚焦的目標身上,但是爬蟲是“一根筋”啊,它可不會自動聚焦,我們還得幫它指引道路。
寫過前端頁面的朋友都知道CSS樣式用過各種選擇器來繫結到對應的節點上,那麼我們也可以通過CSS的選擇器來選中我們想要的元素,從而提取資訊。Chrome中已經準備了CSS選擇器神器,可以生成我們想要元素的選擇器。
具體過程如下:第三步為好好欣賞小哥哥們~
step3:解析頁面
這個時候要介紹頁面解析神器pyquery,這個工具庫可以通過我們所複製的CSS選擇器,在 HTML 頁面中查詢對應元素,並且能很便捷地提取各種屬性。那麼接下來我們就把這個小哥哥解析出來吧。
我們首先安裝 PyQuery
這個包,具體可以使用 pip 包管理器安裝,然後將程式碼修改成如下這樣:
import requests
from pyquery import PyQuery as pq
url = "https://www.nanrentu.cc/sgtp/"
response = requests.get(url)
if response.status_code == 200:
with open("result.html",'w',encoding="utf-8") as f:
f.write(response.text)
# 開始解析
doc = pq(response.text)
# 把複製的選擇器貼上進去
# 選擇對應的節點
imgElement = doc('body > div:nth-child(5) > div > div > div:nth-child(2) > ul > li:nth-child(3) > a > img')
# 提取屬性,獲取圖片連結
imgSrc = imgElement.attr('src')
# 將圖片連結輸出在螢幕上
print(imgSrc)
複製程式碼
step4:儲存目標
這麼好看的小哥哥怎麼能只讓他在網際網路上呆著呢?把他放進硬碟裡的學習資料資料夾裡才是最安全的。接下來,我們就把小哥哥放到碗裡來。
下載圖片的過程其實和抓取HTML頁面的流程是一樣的,也是利用 requests 傳送請求從而獲取到資料流再儲存到本地。
import requests
from pyquery import PyQuery as pq
url = "https://www.nanrentu.cc/sgtp/"
response = requests.get(url)
if response.status_code == 200:
with open("result.html",'w',encoding="utf-8") as f:
f.write(response.text)
doc = pq(response.text)
imgElement = doc('body > div:nth-child(5) > div > div > div:nth-child(2) > ul > li:nth-child(3) > a > img')
imgSrc = imgElement.attr('src')
print(imgSrc)
# 下載圖片
imgResponse = requests.get(imgSrc)
if imgResponse.status_code == 200:
# 填寫檔案路徑 以二進位制的形式寫入檔案
with open('學習檔案/boy.jpg', 'wb') as f:
f.write(imgResponse.content)
f.close()
複製程式碼
此時先來看看效果
四步蟲
至此僅僅十多行程式碼就完成了一個小爬蟲,是不是很簡單。其實爬蟲的基本思路就這四步,所謂複雜的爬蟲就是在這個四步的基礎上不斷演化而來的。爬蟲最終的目的是為了獲取各種資源(文字或圖片),所有的操作都是以資源為核心的。
- 開啟資源
- 定位資源
- 解析資源
- 下載資源
更多的小哥哥
通過上述步驟我們只能獲取到一個小哥哥,集美們就說了,我直接右擊滑鼠下載也可以啊,幹嘛費勁寫爬蟲呢?那接下來,我們就升級一波選擇器,把小哥哥們裝進陣列,統統搞到碗裡來。
重構程式碼
為了以後寫程式碼更方便,要先進行一個簡單的重構,讓程式碼調理清晰。
- 增加入口函式
- 封裝對於圖片的操作
重構後的程式碼如下:
import requests
from pyquery import PyQuery as pq
def saveImage(imgUrl,name):
imgResponse = requests.get(imgUrl)
fileName = "學習檔案/%s.jpg" % name
if imgResponse.status_code == 200:
with open(fileName, 'wb') as f:
f.write(imgResponse.content)
f.close()
def main():
baseUrl = "https://www.nanrentu.cc/sgtp/"
response = requests.get(baseUrl)
if response.status_code == 200:
with open("result.html",'w',encoding="utf-8") as f:
f.write(response.text)
doc = pq(response.text)
imgElement = doc('body > div:nth-child(5) > div > div > div:nth-child(2) > ul > li:nth-child(3) > a > img')
imgSrc = imgElement.attr('src')
print(imgSrc)
saveImage(imgSrc,'boy')
if __name__ == "__main__":
main()
複製程式碼
升級選擇器
有過前端程式設計經驗的同學們可以看出來,Chrome自動生成的選擇器指定了具體的某個子元素,所以就只選中了一個小哥哥,那麼接下來我們要分析出通用的選擇器,把臭弟弟們一鍋端。
多拿著滑鼠點點這個除錯臺,一層層地看這個HTML檔案的元素層級,找到其中相同重複的地方,這就是我們的突破口所在。
我們可以看出圖片都在一個類名為 h-piclist 的 <ul>
標籤中,那麼我們可寫出以下的選擇器 .h-piclist > li > a > img
。這樣就選中了這一頁所有的圖片元素。接著用一個 for 迴圈遍歷就可以了。
import requests
from pyquery import PyQuery as pq
# 引入UUID為圖片命名
import uuid
def saveImage(imgUrl,name):
imgResponse = requests.get(imgUrl)
fileName = "學習檔案/%s.jpg" % name
if imgResponse.status_code == 200:
with open(fileName, 'wb') as f:
f.write(imgResponse.content)
f.close()
def main():
baseUrl = "https://www.nanrentu.cc/sgtp/"
response = requests.get(baseUrl)
if response.status_code == 200:
with open("result.html",'w',encoding="utf-8") as f:
f.write(response.text)
doc = pq(response.text)
# 選則這一頁中所有的目標圖片元素
imgElements = doc('.h-piclist > li > a > img').items()
# 遍歷這些圖片元素
for i in imgElements:
imgSrc = i.attr('src')
print(imgSrc)
saveImage(imgSrc,uuid.uuid1().hex)
if __name__ == "__main__":
main()
複製程式碼
無法下載的圖片
可以看出圖片的連線已經全部拿到了,但是當去下載圖片時卻發生了一些意外,請求圖片竟然沒有反應。這是哪裡出了問題呢?圖片連線全部拿到,證明程式碼沒毛病,把圖片連結放到瀏覽器里正常開啟,證明連線沒毛病,那現在可能就是網路有毛病了。
- 網速慢
- 網路波動
- 對方網站有防爬措施
- ……
這時候因素很多,我們首先用最簡單的方法來解決問題,斷線重連。把筆記本WIFI重啟,重新加入網路,再執行程式。
驚喜來了,臭弟弟們成功入庫。
當然啦,這種方式並不是銀彈,我們需要有更多的技巧來提升爬蟲程式的“演技”,我們的爬蟲程式表現的越像個人,那我們獲取資源的成功率就會越高。
看到這裡,應該跨進爬蟲世界的大門了,如果這個世界有主題曲的話那麼一定是薛之謙的《演員》接下來的教程中會一遍磨礪“演技”,一遍獲取更多的小哥哥。
如果您覺得我們寫得還不錯,記得 點贊 + 關注 + 評論 三連???,鼓勵我們寫出更好的教程?
想要學習更多精彩的實戰技術教程?來圖雀社群逛逛吧。