爬蟲02--requests庫其他操作、免費代理池和案例
阿新 • • 發佈:2022-05-27
昨日回顧
1 爬蟲介紹 -模擬傳送http請求---》獲取到資料(html,json,圖片,視訊)---》資料清洗----》入庫 2 請求庫:requests模組 -跟其他服務互動,使用requests模組傳送請求呼叫 -postman:或使用requests完全自己寫 3 傳送get請求 4 傳送get請求,地址中帶引數 -直接拼在路徑中 -params引數傳入,字典 -url編碼和解碼:中文編成url的編碼形式 5 傳送get請求,攜帶請求頭 -headers引數 -user-agent:客戶端型別 -referer:上一個地址 6 傳送請求,攜帶cookie -請求頭 -以引數形式攜帶 7 傳送post請求 -地址中帶資料:params引數傳入 -請求頭中帶:headers -請求體中:data={}(urlencoed格式),json={} 8 Respons物件屬性,引數 -text:響應的body體,轉成了字串 -content:響應體的二進位制(圖片,視訊) -iter_content:圖片,視訊,迴圈儲存 -編碼 -cookies:一旦登入成功,這個cookies就是認證後的cookies -.json() :把返回的json格式字串直接轉成字典形式 9 編碼問題 # 10 request.session的使用 session = request.session() 使用session物件,傳送請求後,會保持cookie,以後不用每次攜帶cookie
今日內容
1.requests之ssl,超時設定,認證設定,處理異常,上傳檔案 (瞭解)
# http+ssl=https :傳輸過程中加密了---》截獲到,無法解密 # ssl證書:第三方證書 # 證書驗證(大部分網站都是https) import requests respone=requests.get('https://www.12306.cn') # 如果是ssl請求,首先檢查證書是否合法,不合法則報錯,程式終端 # 1:強制使用http連線,不驗證證書 (去掉報錯,但是會報警告) import requests respone=requests.get('https://www.12306.cn',verify=False) # 不驗證證書,報警告,返回200 print(respone.status_code) # 2:去掉報錯,並且去掉警報資訊 import requests from requests.packages import urllib3 urllib3.disable_warnings() # 關閉警告 respone=requests.get('https://www.12306.cn',verify=False) print(respone.status_code) # 3:攜帶證書 (證書, 祕鑰) # 很多網站都是https,但是不用證書也可以訪問,大多數情況都是可以攜帶也可以不攜帶證書 # 知乎\百度等都是可帶可不帶 # 有硬性要求的,則必須帶,比如對於定向的使用者,拿到證書後才有許可權訪問某個特定網站 import requests respone=requests.get('https://www.12306.cn',cert=('/path/server.crt','/path/key')) print(respone.status_code)
# 超時設定
import requests
respone=requests.get('http://127.0.0.1:8000',timeout=3)
print(respone.status_code)
# 認證設定(瞭解) # 官網連結:http://docs.python-requests.org/en/master/user/authentication/ # 舊時的認證 (現在的認證,都是post請求) 彈出一個框,要求你輸入使用者名稱密碼(與alter很類似),此時是無法獲取html的,但本質原理是拼接成請求頭髮送 # 老款的路由器的認證,公司內部可能會看到 import requests from requests.auth import HTTPBasicAuth r=requests.get('xxx',auth=HTTPBasicAuth('user','password')) print(r.status_code) # HTTPBasicAuth可以簡寫為如下格式 import requests r=requests.get('xxx',auth=('user','password')) print(r.status_code)
# 處理異常
import requests
from requests.exceptions import *
try:
respone=requests.get('http://127.0.0.1:8000',timeout=3)
print(respone.status_code)
except ReadTimeout:
print('===:')
except ConnectionError: # 網路不通
print('-----')
except Timeout:
print('aaaaa')
except RequestException:
print('Error')
except Exception as e:
print(e)
# 上傳檔案
import requests
files={'file':open('a.jpg','rb')}
respone=requests.post('http://httpbin.org/post',files=files) # formdata格式
print(respone.status_code)
2.requests使用代理
# 為什麼使用代理?
-網站,訪問頻率過高,封ip,限制ip訪問次數(後端頻率類)
# 使用代理,隱藏訪問者ip,正向代理
-代理伺服器
-免費的:不穩定,不好用
-收費:穩定,好用
import requests
proxies = {'http': 'http://117.68.194.189:1133', }
respone=requests.get('http://127.0.0.1:8000/',proxies=proxies)
print(respone.text)
3.搭建免費代理池
# 本地搭建專案
專案地址: https://hub.xn--p8jhe.tw/jhao104/proxy_pool
1.git clone https://github.com/jhao104/proxy_pool.git
2.pip3 install -r requirements.txt
3.修改setting.py 中的redis連線
4.執行
# 啟動排程程式
python proxyPool.py schedule
# 啟動webApi服務
python proxyPool.py server
# 或直接使用該專案的測試地址返回的ip代理
# 簡單使用
import requests
proxy = requests.get('http://demo.spiderpy.cn/get' ).json().get("proxy")
respone=requests.get('http://127.0.0.1:8000/',proxies={"http": "http://{}".format(proxy))
print(respone.text)
# 封裝一下
import requests
def get_proxy():
return requests.get("http://127.0.0.1:5010/get/").json()
def delete_proxy(proxy):
requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy))
# your spider code
def getHtml():
# ....
retry_count = 5
proxy = get_proxy().get("proxy")
while retry_count > 0:
try:
html = requests.get('http://www.example.com', proxies={"http": "http://{}".format(proxy)})
# 使用代理訪問
return html
except Exception:
retry_count -= 1
# 刪除代理池中代理
delete_proxy(proxy)
return None
4.爬取梨視訊
import requests
import re
# 分析網址規律:?reqType=5&categoryId=9&start=0 文章分類id 文章起始位置
res = requests.get('https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=9&start=0')
print(res.text) # 返回的xml資料
# 解析資料:視訊文章id地址
video_list = re.findall('<a href="(.*?)" class="vervideo-lilink actplay">', res.text)
print(video_list)
# 拼接域名,獲取視訊的真正地址
for video in video_list:
video_id = video.split('_')[-1] # 視訊id
video_url = 'https://www.pearvideo.com/' + video # 視訊文章詳情頁地址
# res=requests.get(video_url) # 該請求就不用訪問了,直接訪問那個Ajax的請求
# print(res.text)
# 直接訪問視訊文章詳情頁地址,沒有返回MP4格式的視訊地址
# 該網站規則時,訪問該地址時,自動再發一個Ajax獲取視訊真正地址
# 故需要,模擬傳送這個Ajax請求 (https://www.pearvideo.com/videoStatus.jsp?contId=視訊id&mrd=0.4930470461853751)
# 訪問發現:
瀏覽器直接訪問 和 從網站詳情頁訪問 返回的資料不一樣
都是瀏覽器操作 說明User-Agent、cookie是一樣的,那就是請求頭的問題了 (對比發現:指定了referer)
# 第一層反爬:需要帶referfer頭 # 動態自己拼
header = {
'Referer': 'https://www.pearvideo.com/%s' % video
}
res = requests.get('https://www.pearvideo.com/videoStatus.jsp?contId=%s&mrd=0.4930470461853751' % video_id,
headers=header)
mp4_url = res.json()['videoInfo']['videos']['srcUrl']
# 第二層反爬:需要將mp4_url地址進行部分替換
mp4_url = mp4_url.replace(mp4_url.split('/')[-1].split('-')[0], 'cont-%s' % video_id)
# 下載視訊
res_video=requests.get(mp4_url)
with open('./viode/%s.mp4'%video_id,'wb') as f:
for line in res_video.iter_content(1024):
f.write(line)
'''
不能播放的:
https://video.pearvideo.com/mp4/third/20211014/ 1634271064903 -11980839-104649-hd.mp4
能播放的:
https://video.pearvideo.com/mp4/third/20211014/ cont-1743691 -11980839-104649-hd.mp4
5.爬取汽車之家
# bs4解析html
# pip3 install beautifulsoup4
import requests
from bs4 import BeautifulSoup
res = requests.get('https://www.autohome.com.cn/news/1/#liststart')
# print(res.text)
# 第一個引數,要解析的文件,第二個引數,解析的解析器('html.parser')
soup = BeautifulSoup(res.text, 'html.parser')
# res=soup.find_all(class_='article',name='ul')
ul_list=soup.find_all(name='ul')
for ul in ul_list:
li_list=ul.find_all(name='li')
for li in li_list:
h3=li.find(name='h3')
if h3:
title=h3.text # 拿出h3標籤的文字內容
# print(title)
url='http:'+li.find('a').attrs['href']
# print(url)
img_url=li.find(name='img').attrs['src']
# print(img_url)
desc=li.find('p').text
# print(desc)
print('''
新聞標題:%s
新聞連線:%s
新聞圖片:%s
新聞摘要:%s
'''%(title,url,img_url,desc))
# 入庫:mysql,建表,欄位,pymysql