Python爬蟲之Requests的基礎運用

1. Requests庫的簡介與安裝

Requests庫是Python的第三方庫,用於網絡請求,是目前爬取網頁最好的三方庫,其特點是簡單、簡潔。

requests 的底層實現其實就是 urllib。Requests 繼承了urllib的所有特性。Requests支持HTTP連接保持和連接池,支持使用cookie保持會話,支持文件上傳,支持自動確定響應內容的編碼,支持國際化的 URL 和 POST 數據自動編碼。

  • 開源地址
  • [官方API文檔]((http://www.python-requests.org)

安裝方法: pip install requests;easy_install requests

作用:模擬瀏覽器發起請求

爬取流程:

  1. 指定url
  2. 發起請求
  3. 獲取響應數據(網頁源代碼)
  4. 保存數據

2. Requests請求方式

2.1 GET請求

requests.get(url,params,**kwargs)

  • url :請求的網站地址
  • params :查詢參數,設置動態爬取
  • **kwargs :字典形式的變量,可添加headers,一些頭部信息等

最基本的GET請求

import requests
url = "http://www.baidu.com"
response = requests.get(url)
# 或者這樣寫
response = requests.request("get",url)

添加 headers 和 查詢參數

import requests
url = "http://www.baidu.com"
kw = {"my":"python"} # 查詢參數
# 頭部信息,用於模擬瀏覽器訪問
headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36"
}
response = requests.get(url=url,params=kw,headers = headers)

2.2 POST請求

requests.post(url, data=None, json=None, **kwargs)

  • url:post請求地址
  • data:添加的參數,字典形式
  • json:(可選)json數據發送到:類的主體
  • **kwargs:字典形式,如headers信息等

最基本的POST請求

import requests
url = "http://www.baidu.com"
response = requests.post(url)

添加 headers 和 data參數

import requests

formdata = {"my":"python"} 

url = "http://www.baidu.com"

headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36"
}

response = requests.post(url, data = formdata, headers = headers)

2.3 獲取響應內容

  • 使用response.text 時,Requests 會基於 HTTP 響應的文本編碼自動解碼響應內容,大多數 Unicode 字符集都能被無縫地解碼。
  • 使用response.content 時,返回的是服務器響應數據的原始二進制字節流,可以用來保存圖片等二進制文件。
  • 推薦使用response.content.deocde()指定編碼
import requests
url = "http://www.baidu.com"
kw = {"my":"python"} # 查詢參數
# 頭部信息,用於模擬瀏覽器訪問
headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36"
}
response = requests.get(url=url,params=kw,headers = headers)
# 查看響應內容,response.text 返回的是Unicode格式的數據
# print (response.text)
# 查看響應內容,response.content返回的字節流數據
# print (response.content)
# 查看完整url地址
print (response.url)

# 查看響應頭部字符編碼
print (response.encoding)

# 查看響應碼
print (response.status_code)
https://m.baidu.com/?my=python&from=844b&vit=fps
utf-8
200
import requests

# 根據協議類型,選擇不同的代理
proxies = {
  "http": "http://12.34.56.79:9527",
  "https": "http://12.34.56.79:9527",
}

response = requests.get("http://www.baidu.com", proxies = proxies)
print( response.text)

3. Requests模塊簡單的使用

3.1 搭建簡易採集器

爬取搜狗首頁的頁面源代碼數據

requests.get()
# 導入requests庫
import requests
# 1. 指定url
url = "http://sogou.com/"
# 2. 發起請求,這裏用get方法的返回值爲響應對象
response = requests.get(url=url)
# 3. 獲取響應數據
# .text:返回的是字符串形式的響應數據
result = response.text
# 4. 保存數據
with open('./sougou.html','w',encoding="utf-8") as fp:
    fp.write(result)

實現一個簡易的網頁採集器,基於搜狗針對指定不同的關鍵字將對應的頁面數據進行爬取

  • 實現參數動態化:請求的url攜帶參數,且我們要將攜帶的參數進行動態化操作,我們就必須:
    1. 將攜帶的動態參數以鍵值對的形式封裝在一點字典中;
    2. 將字典作用在get方法的params參數中即可;
    3. 需要將原始攜帶參數的url中攜帶的參數刪除
import requests
# 1. 指定url,利用sogou訪問Python
url =" https://www.sogou.com/sogou?query=Python"
# 2. 發起請求,這裏用get方法的返回值爲響應對象
response = requests.get(url=url)
# 3. 獲取響應數據
# .text:返回的是字符串形式的響應數據
result = response.text
# 4. 保存數據
with open('./Python1.html','w',encoding="utf-8") as fp:
    fp.write(result)
import requests
# 設置一個輸入的值,加載至url中
keyword = input("請輸入你要查詢的關鍵字")
# 攜帶請求參數的url,如果想要爬取不同關鍵字對應的頁面,
# 我們需要將url攜帶的參數進行動態化
# 實現參數動態化
params = {
    "query":keyword
}
url =" https://www.sogou.com/sogou"
# params參數是一個字典採納數,保存url時攜帶參數
response = requests.get(url=url,params=params)
# 3. 獲取響應數據
# .text:返回的是字符串形式的響應數據
result = response.text
# 4. 保存數據
filename = keyword + ".html"
with open(filename,'w',encoding="utf-8") as fp:
    fp.write(result)
print(filename,"爬取完畢")
請輸入你要查詢的關鍵字Python
Python.html 爬取完畢

在這裏插入圖片描述

上述簡易採集代碼出現了問題:亂碼問題和數據丟失

解決亂碼問題

  • result = response.text 這兒的編碼格式不對,需要修改編碼
import requests
# 設置一個輸入的值,加載至url中
keyword = input("請輸入你要查詢的關鍵字")
# 攜帶請求參數的url,如果想要爬取不同關鍵字對應的頁面,
# 我們需要將url攜帶的參數進行動態化
# 實現參數動態化
params = {
    "query":keyword
}
url =" https://www.sogou.com/sogou"
# params參數是一個字典採納數,保存url時攜帶參數
response = requests.get(url=url,params=params)
# encoding返回的是響應數據的原始的編碼格式,
# 如果給其賦值則表示修改了響應數據的編碼格式
response.encoding = "urf-8"
# 3. 獲取響應數據
# .text:返回的是字符串形式的響應數據
result = response.text
# 4. 保存數據
filename = keyword + ".html"
with open(filename,'w',encoding="utf-8") as fp:
    fp.write(result)
print(filename,"爬取完畢")
請輸入你要查詢的關鍵字Python
Python.html 爬取完畢

在這裏插入圖片描述

處理亂碼後,頁面顯示【異常訪問請求】導致請求失敗

  • 異常的訪問請求:網站後臺檢測出該次請求不是通過瀏覽器發起的請求,而是爬蟲請求。不是通過瀏覽器發起的請求都是異常請求。
  • 網站的後臺是如何知道請求頭中的請求的user-agent判定的

user-agent是什麼?

  • 請求載體的身份標識。

請求載體:

  • 瀏覽器:身份標識統一固定的,可以從抓包工具獲取
  • 爬蟲程序:身份標識各不相同

反爬機制

  • UA檢測:網站後臺監測請求對應的User-Agent,以判定當前請求是否爲異常請求

反反爬策略

  • UA僞裝:作用於部分網站中,從抓包工具中捕獲到某一個基於瀏覽器請求的User-Agent的值,將其僞裝作用到一個字典中,將該字典作用到請求方法(get,post)的headers參數中即可
import requests
# 設置一個輸入的值,加載至url中
keyword = input("請輸入你要查詢的關鍵字")
headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36"
}
# 攜帶請求參數的url,如果想要爬取不同關鍵字對應的頁面,
# 我們需要將url攜帶的參數進行動態化
# 實現參數動態化
params = {
    "query":keyword
}
url =" https://www.sogou.com/sogou"
# params參數是一個字典採納數,保存url時攜帶參數
response = requests.get(url=url,params=params,headers=headers)
# encoding返回的是響應數據的原始的編碼格式,
# 如果給其賦值則表示修改了響應數據的編碼格式
response.encoding = "urf-8"
# 3. 獲取響應數據
# .text:返回的是字符串形式的響應數據
result = response.text
# 4. 保存數據
filename = keyword + ".html"
with open(filename,'w',encoding="utf-8") as fp:
    fp.write(result)
print(filename,"爬取完畢")
請輸入你要查詢的關鍵字Python
Python.html 爬取完畢

在這裏插入圖片描述

3.2 爬取豆瓣電影中的電影的詳情數據

3.2.1 爲什麼需要通過動態加載數據來進行捕獲

爲什麼需要動態加載

  • 我們通過requests模塊進行數據爬取無法每次都實現可見即可得。

什麼是動態加載數據

  • 有些數據是通過非瀏覽器地址欄中的url請求到的數據,而是其他請求到的數據,那麼這些通過其他請求到的數據就是動態加載數據

如何檢測網頁中存在動態加載數據

  • 在網頁中打開抓包工具,捕獲到地址欄中的url對應的數據包,在該數據包中的response選項卡中搜索我們想要抓取的數據
  • 通過抓包工具進行局部搜索,如果搜索到了結果這表示數據不是動態加載的,否則表示數據爲動態加載的。

在這裏插入圖片描述

import requests
# 豆瓣電影,動作片top首頁
url = "https://movie.douban.com/explore#!type=movie&tag=%E5%8A%A8%E4%BD%9C&sort=rank&page_limit=20&page_start=0"

headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36"
}

response = requests.get(url=url,headers=headers)
response.encoding = "utf-8"
result = response.text
with open("./豆瓣電影.html",'w',encoding="utf-8") as fp:
    fp.write(result)
print("爬取完畢")
./爬取完畢

目標

在這裏插入圖片描述

結果

在這裏插入圖片描述

分析通過這種利用url獲取數據就失效了,不能獲取我們想要的數據,其原因可以通過在訪問的目標地址中,通過抓包工具中的network查看,可以看到電影數據是動態加載的。因此需要考慮動態加載數據。

3.2.2 捕獲動態加載的數據

基於抓包工具進行全局搜索

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

定位到動態加載對應的數據包,從該數據包中就可以提取出

  • 請求的ur
  • 請求方式
  • 請求的攜帶參數
  • 看到響應數據

url=https://movie.douban.com/j/search_subjects ?type=movie&tag=%E5%8A%A8%E4%BD%9C&sort=rank&page_limit=20&page_start=0

?後含有請求參數,這裏我們需要做請求參數的動態化,通過將?後參數部分刪除掉,用參數來進行封裝

import requests

url = " https://movie.douban.com/j/search_subjects"
# 請求參數
params = {
    'type': 'movie',
    'tag':'動作',
    'sort': 'rank',
    'page_limit': '20',
    'page_start': '0',
}
headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36"
}
response = requests.get(url=url,params=params,headers=headers)
# 通常是獲取字符串形式,這裏由於是json數據,因此可用.json
# page_text = response.text
# .json()意思爲將獲取的字符串形式的json數據序列化爲字典或者列表
page_text = response.json() 
page_text = page_text['subjects']
# 解析出電影名稱加評分
for moive in page_text:
    name = moive["title"]
    score = moive['rate']
    print(name,":",score)
這個殺手不太冷 : 9.4
蝙蝠俠:黑暗騎士 : 9.2
指環王3:王者無敵 : 9.2
指環王2:雙塔奇兵 : 9.1
指環王1:魔戒再現 : 9.0
黑客帝國 : 9.0
讓子彈飛 : 8.8
搏擊俱樂部 : 9.0
V字仇殺隊 : 8.9
七武士 : 9.2
阿凡達 : 8.7
頭號玩家 : 8.7
加勒比海盜 : 8.7
殺人回憶 : 8.8
勇敢的心 : 8.9
蝙蝠俠:黑暗騎士崛起 : 8.8
功夫 : 8.6
復仇者聯盟4:終局之戰 : 8.5
釜山行 : 8.5
縱橫四海 : 8.8

我們通過修改這裏面的參數,如我們將’page_start’: ‘0’,爲’page_start’: ‘20’,就可以實現想要的數據的獲取了。

import requests

url = " https://movie.douban.com/j/search_subjects"
# 請求參數
params = {
    'type': 'movie',
    'tag':'動作',
    'sort': 'rank',
    'page_limit': '20',
    'page_start': '20',
}
headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36"
}
response = requests.get(url=url,params=params,headers=headers)
# 通常是獲取字符串形式,這裏由於是json數據,因此可用.json
# page_text = response.text
# .json()意思爲將獲取的字符串形式的json數據序列化爲字典或者列表
page_text = response.json() 
page_text = page_text['subjects']
# 解析出電影名稱加評分
for moive in page_text:
    name = moive["title"]
    score = moive['rate']
    print(name,":",score)
蜘蛛俠:平行宇宙 : 8.6
英雄本色 : 8.7
黑客帝國3:矩陣革命 : 8.7
諜影重重3 : 8.8
被解救的姜戈 : 8.7
東邪西毒 : 8.6
終結者2:審判日 : 8.7
瘋狂的麥克斯4:狂暴之路 : 8.6
攻殼機動隊 : 9.0
紅海行動 : 8.3
諜影重重2 : 8.7
新龍門客棧 : 8.6
小蘿莉的猴神大叔 : 8.4
福爾摩斯二世 : 9.5
黑客帝國2:重裝上陣 : 8.6
諜影重重 : 8.6
黑鷹墜落 : 8.7
東邪西毒:終極版 : 8.7
無間道2 : 8.5
鋼鐵俠 : 8.3

由於利用抓包工具進行全局搜索不一定每次都能夠搜索到對應的數據包,其原因是如果動態加載的數據是經過加密的密文數據,我們就認爲是加密的數據。因此需要進行解密,後面會見。

3.2.3 分頁數據的爬取操作

爬取肯德基的餐廳位置數據

  • url: http://www.kfc.com.cn/kfccda/storelist/index.aspx

分析步驟

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

分析

  • 通過關鍵字查詢文本框中錄入關鍵字按下搜索按鈕,發起的是一個ajax請求。通過搜索關鍵字可以看出其網址並未發生變化,因此判定當前頁面刷新出來的位置信息一定是通過ajax請求到的數據。
  • 基於抓包工具可以定位到該ajax請求的數據包,我們可從該數據包中捕獲到:
  1. 請求的url
  2. 請求方式
  3. 請求的攜帶參數
  4. 看到的響應數據
import requests
url = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"
          }
data = {
    'cname':' ',
    'pid':' ',
    'keyword': '北京',
    'pageIndex': '1',
    'pageSize': '10',
}
# data參數時post方法中處理參數動態化的參數
response = requests.post(url=url,headers=headers,data=data)
response.status_code
200
response.text
'{"Table":[{"rowcount":0}],"Table1":[]}'

這裏沒有獲取到數據,可能被反爬了。弄了兩天了,暫時就這樣吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章