1. 程式人生 > 實用技巧 >Python爬蟲基礎入門看完這一篇就學會了

Python爬蟲基礎入門看完這一篇就學會了

前言

本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯絡我們以作處理。

PS:如有需要Python學習資料的小夥伴可以加點選下方連結自行獲取

python免費學習資料以及群交流解答點選即可加入


大家好,今天我們來聊聊Python爬蟲的基礎操作,反正我是這樣入門了,哈哈。

其實,一開始學python的時候,我是衝著資料處理分析去了,那個pandas什麼的。後來,發現爬蟲挺好玩,可以解決純手工採集網上資料的繁瑣問題,比如我用的比較多的爬取taptap某遊戲評價內容、某視訊網站某劇的彈幕、某評的店鋪資訊、某牙主播資訊等等。


關於爬蟲,我也只會一些比較基礎的操作,不過個人經驗上感覺這些基礎基本可以滿足比較常規化的需求。對於進階的爬蟲技巧,大家在瞭解熟悉爬蟲基礎後自然會有進階學習的思路與途徑。

接下來,我們進入主題吧~

0.爬蟲基礎流程

把爬蟲的過程模組化,基本上可以歸納為以下幾個步驟:

  • [√] 分析網頁URL:開啟你想要爬取資料的網站,然後尋找真實的頁面資料URL地址;
  • [√] 請求網頁資料:模擬請求網頁資料,這裡我們介紹requests庫的使用;
  • [√] 解析網頁資料:根據請求獲得的網頁資料我們用不同的方式解析成我們需要用的資料(如果網頁資料為html原始碼,我們用Beautiful Soup、xpath和re正則表示式三種解析;若網頁資料為json格式,我們可以直接用字典列表等基礎知識處理)
  • [√] 儲存網頁資料:一般來說,解析後的資料是比較結構化的,可以儲存為txt、csv、json或excel等文字,亦或者可以儲存在資料庫如MySql、MongoDB或SqlLite中。

1.分析網頁URL

當我們有一個目標網站,有時候會發現對於靜態網頁,我們只需要把網頁位址列中的URL傳到get請求中就可以直接取到網頁的資料。但如果這是動態網頁,我們便無法通過簡單的傳遞網頁位址列的URL給get請求來獲取網頁資料,往往這個時候,我們進行翻頁的時候還會發現網頁位址列中的URL是不會發生變化的。

接下來,我們來分別介紹這兩種情況下如何獲取真實的頁面資料URL地址。

1.1 靜態網頁

對於靜態網頁來說,其實網頁位址列中的URL就是我們需要的。

以 貝殼二手房網(https://bj.ke.com/ershoufang/) 為例,我們可以看到進行翻頁(如到第2頁)的時候網頁位址列的URL變為了(

https://bj.ke.com/ershoufang/pg2/)。型別這種情況,多半就是靜態網頁了,而且翻頁的URL規律十分明顯。

1.2 動態網頁

對於動態網頁來說,我們一般可以通過以下幾個步驟找到真實URL地址:

1.需要按“F12”進入到瀏覽器的開發者模式;
2.點選“Network”—>XHR或JS或者你全部查詢看;
3.進行翻頁(可能是點選下一頁或者下滑載入更多);
4.觀察第2步中name模組的內容變化,尋找。

以 虎牙星秀區(https://www.huya.com/g/xingxiu) 為例,我們可以看到進行翻頁(如到第2頁)的時候網頁位址列的URL沒有發生任何改變。

為了便於找到真實的URL地址,我們可以在開發者模式中找以下截圖中的幾點,preview是預覽結果,可以便於我們進行匹配定位具體的Name。

當我們定位到具體的Name後,右側選擇Headers可以檢視到請求網頁需要的相關引數資訊,而且比較好擬清其變化規律。以虎牙星秀為例,其真實URL地址及變化規律如下:

真實URL地址

2.請求網頁資料

當我們確定了真實資料的URL後,這裡便可以用requests的get或post方法進行請求網頁資料。

關於requests庫的更多使用方式,大家可以前往(https://requests.readthedocs.io/zh_CN/latest/)檢視。

2.1 傳送get請求

In [1]: import requests

In [2]: url = 'https://bj.ke.com/ershoufang/'

In [3]: r = requests.get(url)

In [4]: type(r)
Out[4]: requests.models.Response

In [5]: r.status_code
Out[5]: 200

我們得到的是一個Response物件,如果我們想要獲取網頁資料,可以使用text或content屬性來獲取,另外如果獲取的網頁資料是json格式的則可以使用Requests 中內建的json()解碼器方法,助你處理json 資料。

  • r.text:字串型別的資料,一般網頁資料為文字類用此屬性
  • r.content:二進位制型別的資料,一般網頁資料為視訊或者圖片時用此屬性
  • r.json():json資料解碼,一般網頁資料為json格式時用此方法
    對於一些動態網頁,請求的網址是基礎url和關鍵字引數組合而成,這個時候我們可以使用 params 關鍵字引數,以一個字串字典來提供這些引數。
In [6]: url = 'https://www.huya.com/cache.php'
   ...: parames = {
   ...:     'm': 'LiveList',
   ...:     'do': 'getLiveListByPage',
   ...:     'gameId': 1663,
   ...:     'tagAll': 0,
   ...:     'page': 2, # 翻頁變化的就是這個引數
   ...:     }
   ...: 
   ...: r = requests.get(url, params=parames)

In [7]: r.url
Out[7]: 'https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=2'

2.2 傳送post請求

通常,你想要傳送一些編碼為表單形式的資料——非常像一個 HTML 表單。要實現這個,只需簡單地傳遞一個字典給 data 引數。你的資料字典在發出請求時會自動編碼為表單形式:

>>> payload = {'key1': 'value1', 'key2': 'value2'}

>>> r = requests.post("http://httpbin.org/post", data=payload)

很多時候你想要傳送的資料並非編碼為表單形式的。如果你傳遞一個 string 而不是一個 dict,那麼資料會被直接釋出出去。

>>> import json

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, data=json.dumps(payload))

此處除了可以自行對 dict 進行編碼,你還可以使用 json 引數直接傳遞,然後它就會被自動編碼。

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, json=payload)

2.3 定製請求頭

在模擬請求時,如果不設定請求頭的話是比較容易被網站發現是來自爬蟲指令碼,一些網站會對這種模擬請求進行拒絕。因此我們可以簡單設定一下請求頭做偽裝,一般是設定瀏覽器。

headers = {
     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
     }
r = requests.get(url, headers=headers)

其實,對於請求頭還可以設定很多引數,具體大家可以在實際爬蟲過程中在開發者模式看看裡面的請求頭模組進行分析處理。

虎牙星秀請求頭

2.4 響應碼

我們在 2.1 中看到獲取響應碼的是通過 r.status_code屬性,一般來說如果 返回 數字 200,則表示成功獲取了網頁資料。

響應碼分為五種型別,由它們的第一位數字表示:1xx:資訊,請求收到,繼續處理 2xx:成功,行為被成功地接受、理解和採納 3xx:重定向,為了完成請求,必須進一步執行的動作 4xx:客戶端錯誤,請求包含語法錯誤或者請求無法實現 5xx:伺服器錯誤,伺服器不能實現一種明顯無效的請求

3.解析資料

上面有提到我們請求的網頁資料有Html原始碼文字或者是json字串文字,兩者的解析方式不同。以下我們分別進行簡單說明,大家在實際操作中視情況而定即可。

3.1 網頁html文字解析

對於網頁html文字來說,這裡介紹Beautiful Soup、xpath和re正則表示式三種解析方法。

以貝殼二手房最新房源(https://bj.ke.com/ershoufang/co32/)為例,其html原始碼如下,我們通過get請求後的資料進行解析。

3.1.1 Beautiful Soup

關於Beautiful Soup庫的更多使用方式,大家可以前往檢視(https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/)

首先安裝pip install beautifulsoup4。

我們將網頁html文字內容r.text當作第一個引數傳給BeautifulSoup物件,該物件的第二個引數為解析器的型別(這裡使用lxml),此時就完成了BeaufulSoup物件的初始化。然後,將這個物件賦值給soup變數。

from bs4 import BeautifulSoup
import requests

url = 'https://bj.ke.com/ershoufang/co32/'
r = requests.get(url)
soup = BeautifulSoup(r.text, 'lxml')

獲取房源的名稱的程式碼如下:

# 獲取全部房源 所在的節點
sellList = soup.find(class_="sellListContent")
# 獲取全部房源節點列表
lis = sellList.find_all('li',class_="clear")
# 選取第一個房源節點
div = lis[0].find('div',class_="info clear")
# 採集房源名稱
title = div.find('div',class_="title")
print(title.text)
明春西園 2室1廳 南 北

3.1.2 xpath

XPath,全稱 XML Path Language,即 XML 路徑語言,它是一門在 XML 文件中查詢資訊的語言。

首先安裝lxmlpip install lxml。

常見的規則如下:

首先匯入 lxml 庫的 etree 模組,然後宣告一段 HTML 文字,呼叫 HTML 類進行初始化,成功構造一個 XPath 解析物件。

from lxml import etree
import requests

url = 'https://bj.ke.com/ershoufang/co32/'
r = requests.get(url)
html = etree.HTML(r.text)

通過copy獲取的xpath://*[@id="beike"]/div[1]/div[4]/div[1]/div[4]/ul/li[1]/div/div[1]/a

# 獲取 全部房源所在節點 ul,根據屬性匹配精準查詢
ul = html.xpath('.//ul[@class="sellListContent"]')[0]
# 獲取房源列表
lis = ul.xpath('.//li[@class="clear"]')
# 選取第一個房源節點
li = lis[0]
# 獲取其房源名稱
li.xpath('./div/div[1]/a/text()')
['明春西園 2室1廳 南 北']

3.1.3 re正則

關於re正則解析網頁html大家也可以前往檢視此前釋出的文章《對著爬蟲網頁HTML學習Python正則表示式re》。

# 找到房源名稱所在的前後字元,然後組成正則表示式
re.findall(r'<a class="VIEWDATA CLICKDATA maidian-detail" title="(.*?)"',r.text,re.S)[0]
'明春西園 2室1廳 南 北'

3.2 json文字解析

在requests提供了r.json(),可以用於json資料解碼,一般網頁資料為json格式時用此方法。除此之外,還可以通過json.loads()和eval()方法進行處理。

url = 'https://www.huya.com/cache.php'
parames = {
     'm': 'LiveList',
     'do': 'getLiveListByPage',
     'gameId': 1663,
     'tagAll': 0,
     'page': 2, # 翻頁變化的就是這個引數
     }

r = requests.get(url, params=parames)
data = r.json()
type(data)
dict

如此解析後得到的資料就是字典,然後我們在看看字典中哪些欄位是我們需要的,取出即可。

4.儲存資料

當我們獲取了到想要的資料後,便可以寫入本地了。

對於文字類資料,可以通過csv模組或pandas模組進行寫入到本地csv檔案或excel檔案;同時也可以用pymysql模組寫入到資料庫或者sqlite寫入到本地資料庫。

對於視訊或者圖片,可以open一個檔案然後寫入二進位制內容後儲存本地亦可。

關於儲存資料大家可以結合實際案例進行學習。