一、前言
爬蟲一直是Python的一大應用場景,差不多每門語言都可以寫爬蟲,但是程序員們卻獨愛Python。之偏愛Python就是因為她簡潔的語法,我們使用Python可以很簡單的寫出一個爬蟲程序。本篇博客將以Python語言,用幾個非常簡單的例子帶大家入門Python爬蟲。
二、網絡爬蟲
如果把我們的因特網比作一張復雜的蜘蛛網的話,那我們的爬蟲就是一個蜘,我們可以讓這個蜘蛛在網上任意爬行,在網中尋找對我們有價值的“獵物”。
1.向服務器發送網絡請求
2.瀏覽器接收并處理你的請求
3.瀏覽器返回你需要的數據
4.瀏覽器解析數據,并以網頁的形式展現出來
我們可以將上面的過程類比我們的日常購物:
1.和老板說我要杯珍珠奶茶
2.老板在店里看看有沒有你要的東西
3.老板拿出做奶茶的材料
4.老板將材料做成奶茶并給你
上面買奶茶的例 子雖然有些不恰當的地方,但是我覺得已經能很好的解釋什么是網絡請求了。打開UC瀏覽器 查看更多精彩圖片在知道網絡請求是什么之后,我們就可以來了解一下什么是爬蟲了。實際上爬蟲也是網絡請求,通常情況下我們通過瀏覽器,而我們的爬蟲則是通過程序來模擬網絡請求這一過程。但是這種基礎的網絡請求還算不上是爬蟲,爬蟲通常都是有目的的。比如我想寫一個爬取美女圖片,我們就需要對我們請求到的數據進行一些篩選、匹配,找到對我們有價值的數據。而這一從網絡請求到數據爬取這整個過程才是一個完整的爬蟲。打開UC瀏覽器 查看更多精彩圖片有些時候網站的反爬蟲做的比較差,我們可以直接在瀏覽器中找到它的API,我們通過API可以直接獲取我們需要的數據,這種相比就要簡單許多。
三、簡單的爬蟲
簡單的爬蟲就是單純的網絡請求,也可以對請求的數據進行一些簡單的處理。Python提供了原生的網絡請求模塊urllib,還有封裝版的requests模塊。相比直線requests要更加方便好用,本文使用requests進行網絡請求。
3.1、爬取一個簡單的網頁
在我們發送請求的時候,返回的數據多種多樣,有HTML代碼、json數據、xml數據,還有二進制流。我們先以百度首頁為例,進行爬取:
import requests # 以get方法發送請求,返回數據 response = requests. get () # 以二進制寫入的方式打開一個文件 f = open( 'index.html' , 'wb' ) # 將響應的字節流寫入文件 f.write(response.content) # 關閉文件 f.close()
下面我們看看爬取的網站打開是什么樣子的:
這就是我們熟悉的百度頁面,上面看起來還是比較完整的。我們再以其它網站為例,可以就是不同的效果了,我們以CSDN為例:
可以看到頁面的布局已經完全亂了,而且也丟失了很多東西。學過前端的都知道,一個網頁是由html頁面還有許多靜態文件構成的,而我們爬取的時候只是將HTML代碼爬取下來,HTML中鏈接的靜態資源,像css樣式和圖片文件等都沒有爬取,會看到這種很奇怪的頁面。
3.2、爬取網頁中的圖片
import requests # 準備url # 發送get請求 response = requests.get(url) # 以二進制寫入的方式打開圖片文件 f = open('test.jpg', 'wb') # 將文件流寫入圖片 f.write(response.content) # 關閉文件 f.close()
可以看到,代碼和上面網頁爬取是一樣的,只是打開的文件后綴為jpg。實際上圖片、視頻、音頻這種文件用二進制寫入的方式比較恰當,而對應html代碼這種文本信息,我們通常直接獲取它的文本,獲取方式為 response.text ?
import re import requests # 要爬取的網站 url = # 獲取網頁源碼 response = requests.get(url) # 匹配源碼中的圖片資源 results = re.findall("img[\\s\\S]+src=\"(.+)\"", response.text) # 用于命名的變量 name = 0 # 遍歷結果 for result in results: # 在源碼中分析出圖片資源寫的是絕對路徑,完整url是主站+絕對路徑 img_url = url+result #圖片 f = open(str(name) + '.jpg', 'wb') f.write(requests.get(img_url).content) f.close() name += 1
上面我們就完成了一個網站的爬取。在匹配時我們用到了正則表達式,因為正則的內容比較多,在這里就不展開了,有興趣的讀者可以自己去了解一下,這里只說一個簡單的。Python使用正則是通過re模塊實現的,可以調用 findall 匹配文本中所有符合要求的字符串。該函數傳入兩個參數,第一個為正則表達式,第二個為要匹配的字符串,對正則不了解的話只需要知道我們使用該正則可以將圖片中的src內容拿出來。
使用BeautifulSoup解析HTML
BeautifulSoup是一個用來分析XML文件和HTML文件的模塊,我們前面使用正則表達式進行模式匹配,但自己寫正則表達式是一個比較繁瑣的過程,而且容易出錯。如果我們把解析工作交給BeautifulSoup會大大減少我們的工作量,在使用之前我們先安裝。
四、4.1、BeautifulSoup的安裝和簡單使用
我們直接使用pip安裝: ?
pip install beautifulsoup4
模塊的導入如下: ? ??
from bs4 import BeautifulSoup
下面我們就來看看BeautifulSoup的使用,我們用下面HTML文件測試: ?
!DOCTYPE html html lang = "en" head meta charset = "UTF-8" title Title / title / head body img class = "test" src = "1.jpg" img class = "test" src = "2.jpg" img class = "test" src = "3.jpg" img class = "test" src = "4.jpg" img class = "test" src = "5.jpg" img class = "test" src = "6.jpg" img class = "test" src = "7.jpg" img class = "test" src = "8.jpg" / body / html
上面是一個非常簡答的html頁面,body內包含了8個img標簽,現在我們需要獲取它們的src,代碼如下:
from bs4 import BeautifulSoup # 讀取html文件 f = open( 'test.html' , 'r' ) str = f.read() f.close() # 創建BeautifulSoup對象,第一個參數為解析的字符串,第二個參數為解析器 soup = BeautifulSoup(str, 'html.parser' ) # 匹配內容,第一個為標簽名稱,第二個為限定屬性,下面表示匹配class為test的img標簽 img_list = soup.find_all( 'img' , { 'class' : 'test' }) # 遍歷標簽 for img in img_list: # 獲取img標簽的src值 src = img[ 'src' ] print(src)
解析結果如下: ?
1 .jpg 2 .jpg 3 .jpg 4 .jpg 5 .jpg 6 .jpg 7 .jpg 8 .jpg
正好就是我們需要的內容。
4.2、BeautifulSoup實戰
主站+href值 ,知道了這個我們就可以進行下一步的操作了,我們先從主站爬取跳轉的url: ?
import requests from bs4 import BeautifulSoup # 主站 url = # 模擬瀏覽器訪問 headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } # 發送請求 response = requests.get(url, headers=headers) # 獲取BeautifulSoup對象 soup = BeautifulSoup(response.text, 'html.parser' ) # 解析出符合要求的a標簽 video_list = soup.find_all( 'a' , { 'class' : 'actwapslide-link' }) # 遍歷標簽 for video in video_list: # 獲取herf并組拼成完整的url video_url = video[ 'href' ] video_url = url + video_url print(video_url)
輸出結果如下:
我們只爬取一個就好了,我們進入第一個網址查看源碼,發現了這么一句:
var contId= "1674906" ,liveStatusUrl= "liveStatus.jsp" ,liveSta= "" ,playSta= "1" ,autoPlay=! 1 ,isLiving=! 1 ,isVrVideo=! 1 ,hdflvUrl= "" ,sdflvUrl= "" ,hdUrl= "" ,sdUrl= "" ,ldUrl= "" ,srcUrl=,vdoUrl=srcUrl,skinRes=,videoCDN= "http://video.pearvideo.com" ;
其中srcUrl就包含了視頻文件的網站,但是我們肯定不能自己一個網頁一個網頁自己找,我們可以使用正則表達式:
import re # 獲取單個視頻網頁的源碼 response = requests.get(video_url) # 匹配視頻網址 results = re.findall('srcUrl= "(.*)" ', response.text) # 輸出結果 print(results)
結果如下:
然后我們就可以這個視頻了:
with open ( 'result.mp4' , 'wb' ) as f: f.write(requests.get(results[ 0 ], headers=headers).content)
?
import re import requests from bs4 import BeautifulSoup # 主站 # 模擬瀏覽器訪問 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } # 發送請求 response = requests.get(url, headers=headers) # 獲取BeautifulSoup對象 soup = BeautifulSoup(response.text, 'html.parser') # 解析出符合要求的a標簽 video_list = soup.find_all('a', {'class':'actwapslide-link'}) # 遍歷標簽 video_url = video_list[0]['href'] response = requests.get(video_url) results = re.findall('srcUrl= "(.*)" ', response.text) with open('result.mp4', 'wb') as f: f.write(requests.get(results[0], headers=headers).content)
到此我們就從簡單的網頁到圖片再到視頻實現了幾個不同的爬蟲。