第一章:爬蟲基礎
1.1 通用爬蟲與聚焦爬蟲
通用爬蟲:主要將互聯網上的網頁下載到本地,形成一個互聯網的鏡像備份。
聚焦爬蟲:通過特定的規則對網頁內容進行與需求相關的爬取。
1.2 http協議
首先看一下在瀏覽器中是怎麼樣發送一個http請求的過程:
- 當你輸入網址(也叫url)回車的時候,瀏覽器會向服務器發送Request請求去獲取該網址的html文件。
- 服務器將對應的html文件作爲Response對象返回給瀏覽器。
- 當瀏覽器解析Response中的html文件時,如果發現此文件還引用了其他的文件,例如js文件、css文件、圖片等,瀏覽器會自動再發送請求去獲取這些文件。
- 當所有文件都成功獲取了之後,網頁會自動解析展示給用戶。
1.3 URL詳解
URL
:是Uniform Resource Locator
的簡寫,叫做統一資源定位符。
URL的組成:scheme://host:post/path?queryString#anchor
- scheme:訪問協議,一般是http、https、ftp等。
- host:主機名/域名,比如
www.baidu.com
。定位到主機。 - post:端口號。定位到應用。因爲一臺主機可能作爲多個應用的服務器,所以需要用端口號來識別。
- path:查找路徑。例如
www.baidu.com/login
。定位到具體的文件。 - queryString:查詢字符串/請求參數。例如
www.baidu.com/s?wd=python
瀏覽器發送Request請求時會把請求參數解析爲{“wd”:”python”}
發送到後端,後端會對參數做相應的處理。 - anchor:錨點。前端用做網頁定位的。比如很多網絡小說的章節跳轉,多數用的就是錨點。
tips:http的端口默認是80,https的端口默認是443
1.4 常見的請求方式
在HTTP
請求中,定義了八種請求方式,常見的有get
和post
:
- get請求:直接從服務器獲取數據,不會對服務器資源產生影響。get請求攜帶的參數長度有限制,攜帶參數的方式就是在
url
後面加上queryString
。 - post請求:向後臺發送比較重要的數據(登錄)、文件上傳。參數長度沒有限制,攜帶參數的方式放在Request body中。
更詳細的get和post解釋可以看:GET和POST兩種基本請求方法的區別 這篇博客利用了很形象的例子解釋了這兩種請求方式之間的聯繫。
tips:
- get比post更不安全。因爲get會把請求參數直接顯示到
url
中 - get跟post在技術上可以相互實現
- 一般情況下:get產生一個TCP數據包;post產生兩個TCP數據包。
- 在
HTTP
協議中,向服務器發送一個請求分爲三部分:第一是把數據放在url
中,第二是把post
請求(如果有)放在Request body
中,第三是把數據放在head
中。
1.5 請求頭常見參數
User-Agent
:請求時顯示的瀏覽器名稱。後期爬蟲會經常用到這個,因爲我們提供爬蟲發送請求時默認的User-Agent是python,所以我們需要改名字,讓服務器認不出我們。
Referer
:表名這個請求時從哪個 url 跳轉過來的。一般也可以用來做反爬蟲技術,因爲有些頁面必須是要從指定的 url 跳轉纔可以訪問。
cookie
:暫時存儲網頁的信息。因爲http
協議是無狀態的,所謂的無狀態就比如當同一個用戶發送兩次請求時,服務器沒有能力知道這兩次請求是否來自同一個人,所以需要使用cookie來做標識,這樣每次訪問的時候cookie就會跟服務器說,我就是那個靚仔。
1.6 常見狀態碼
200
:一切正常
301
:永久重定向。以後再訪問此網址的時候都會跳轉到新的網址。
302
:臨時重定向。在接下來一段時間,訪問此網址的時候都會跳轉到新的網址。
404
:資源不存在
403
:權限不足
5開頭
:服務器內部出錯(一般是代碼寫錯)
1.7 分析調試界面
在一個頁面中,按下F12
或右鍵->檢查元素
可以跳轉到開發者調試界面,開發者調試界面可以查看一些關於網站的一些信息。以後爬蟲需要經常利用它進行抓包,頁面的分析等操作。
控制檯的樣子一般長這樣:
Elements:網頁的html源代碼內容。
Console:控制檯,用來進行一些JS操作。
Source:網站所要用到的資源文件。
Network:查看該網頁向服務器發送了哪些請求。(常用)
1.8 urllib庫
urllib
是python
一個基本的網絡請求庫,可以模擬瀏覽器行爲,向指定服務器發送一個請求,並可以保存服務器返回的數據。在使用這個庫之前需要先導入from urllib import request
下面看看這個庫裏面使用的一些函數吧:
urlopen函數: 發送網絡請求,返回 Response
對象。
格式:urlopen(url,data=None)
參數:
- url:要請求的網址。默認爲get請求
- data:請求參數。默認值爲None,如果設置了此值就變成post請求
from urllib import request # 1.導入urllib庫
url = 'https://www.baidu.com/baidu'
# 2.獲取Response對象
res = request.urlopen(url)
print(res.read()) # 獲取網頁源代碼
print(res.status) # 獲取返回狀態碼
urlretrieve函數:將服務器的一個文件保存到本地
格式:urlretrieve(url,filename)
參數:
- url:要請求的網址。默認爲get請求
- filename:保存到本地時文件的名字(可以指定路徑)
from urllib import request # 1.導入urllib庫
url = 'https://www.baidu.com'
request.urlretrieve(url, 'baidu.html')
此時你會發現,當前項目文件夾就多出了個baidu.html
的文件。那麼如果你想把文件下載到指定的目錄可以request.urlretrieve(url, 'D://baidu.html')
,執行代碼之後文件就跑到D盤下了。
此函數功能很強大,比如你想爬取漂亮美眉的圖片,可以寫個while循環然後寫好美眉圖片的路徑,那麼你就可以爲所欲爲了。
request.Request類
前面的urlopen
是不知道如何僞裝的,只能傻傻的告訴服務器說:我是爬蟲,我要爬取你的信息,你給不給我,不給我就走了。這時,“兇”一點的服務器就直接上來打它,MD,還沒見過這麼囂張的爬蟲呢。
所以,如果我們要能更安全的爬取一些信息,我們需要作出一些僞裝,例如前面提到的User-Agent
。如果我們需要配置這些信息,那就需要使用到request.Request
。
from urllib import request
url = 'https://www.baidu.com/baidu'
# 設置請求頭
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/82.0.4077.0 Safari/537.36'
}
# 僞裝User-Agent
req = request.Request(url, headers=headers)
res = request.urlopen(req) # 此時不再需要傳url
print(res.read().decode('utf-8')) # 將二進制內容解碼成utf-8
到了這一步,媽媽就不再擔心我因爲“名字”被打了。
那麼問題來了,這個User-Agent
要怎麼設置呢?
其實很簡單,用瀏覽器隨便打開一個網頁,然後按F12
進入開發者調試工具,然後來到Network
,接着隨便點擊一個請求,找到請求頭,然後複製裏面的User-Agent
到代碼中,然後改成字典的形式就可以了。
1.9 小實戰
Request類除了可以設置User-Agent
還可以設置參數(data)跟請求方式(method)。
讓我們把以上內容跟Request類結合爬取一下拉勾網吧。
首先隨便找到個可以分頁的地方(這裏以爬取分頁信息爲例),按F12
找到 Network
在衆多請求中找到獲取分頁信息的請求(在拉鉤網應該是.json
結尾且type爲xhr
的請求),找到該請求之後你會發現,這個請求的方式爲post
,
複製上面的referer
,因爲我按了第二頁,所以他的referer
的意思是從第一頁跳轉過來的。
複製User-Agent
僞裝下自己。
分析Form Data
,我這裏的是Google瀏覽器其他瀏覽器的方式大同小異。可以看到
有這樣的一些參數:
first:true
表示是否在第一頁pn:1
表示當前的頁數。kd:Python
搜索的職業是python
下面來看看代碼:
from urllib import request
from urllib import parse
url = 'https://www.lagou.com/guangzhou-zhaopin/Python/4/?filterOption=3&sid=4d3fa0ba0cc14b84a9e25164db9ca571'
# 設置請求頭和referer
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/82.0.4077.0 Safari/537.36',
"referer": "https://www.lagou.com/guangzhou-zhaopin/Python/4/?filterOption=3&sid=4d3fa0ba0cc14b84a9e25164db9ca571"
}
# 設置請求參數,如這裏設置請求第四頁的內容
data = {
"first": "false",
"pn": 4,
"kd": "python"
}
# 設置POST請求,且設置POST請求的參數
req = request.Request(url, headers=headers, data=parse.urlencode(data).encode('utf-8'), method='POST')
res = request.urlopen(req)
print(res.read().decode('utf-8'))
這裏介紹parse.urlencode
方法,這個方法的作用就是幫我們將key:value這樣的鍵值對轉換成"key=value"這樣的字符串。
怎麼樣,到了這一步是不是就小有成就了,這只是初步的爬取一個網頁,經過以後的學習就可以爬取自己想要的數據,不僅僅是一個網頁啦,而是具體的文字啊,信息啊什麼的,加油,讓我們一起努力!
小結:
- 由於很多網站採取的都是ajax異步請求,所以找這些異步請求的時候一般找有ajax字眼並且是json文件的
- 爬蟲時能在網頁的請求頭中複製的就儘量在請求頭中複製。
由於以後這個爬蟲教程主要是學Request庫來進行網絡爬取,所以在這裏就不過多的介紹urllib
庫了。並且下章開始就使用Request庫了。