一、爬蟲的基礎內容
1、基本概念和用途
1.1、概念:
- 模擬瀏覽器、發送請求,獲取響應。(只能獲取客戶端所展示出來的數據)
1.2、特點:知識碎片化,針對不同的網站對應的方法也不同。
- 爬蟲:模擬客戶端訪問,抓取數據。
- 反爬:保護重要數據,阻止惡意網絡攻擊
- 反反爬:針對反爬的措施。
1.3、作用
- 數據采集
- 軟件測試
- 搶票
- 網絡安全
- web漏洞掃描
2、爬蟲的分類
2.1、根據爬取網站的數量,可以分為
2.1.1、通用爬蟲
①特點:爬取網站數量沒有上線。
示例:搜索引擎
2.1.2、聚焦爬蟲(*)
①特點:爬取網站數量有上限,有明確的目標。
②分類:
功能性爬蟲
①特點:不獲取數據,只為實現某一功能。
示例:投票 / 搶票 / 短信轟炸等。
數據增量性爬蟲
①特點:獲取數據用于后續分析
②分類
- url與數據同時變化? ? ? ? -- 整條新數據
- url不變,數據裱花? ? ? ? -- 數據部分更新
3、爬蟲的基本流程
3.1、流程
- url(網站資源定位符)
- 對url發送網絡請求,獲取網絡請求的響應
- 解析響應,提取數據
- 保存數據
3.1.1、確認目標:目標url:www.baidu.com
3.1.2、發送請求:發送網絡請求,獲取到特定的服務端給你響應。
3.1.3、提取數據:從響應中提取特定的數據? ? ? ? jsonpath / xpath / re
3.1.4、保存數據:本地(html、json、txt)、數據庫
獲取到的響應中,有可能會提取到還需要繼續發送請求的url,可以拿著解析到的url繼續發送請求
robots協議并不是一個規范,只是約定俗成。
二、http協議以及請求頭
1、網絡通信
1.1、步驟
- 電腦(瀏覽器):? ?url? ? ? --? ?www.baidu.com? ? ? 域名
- DNS服務器:IP地址標注服務器,返回響應
- DNS服務器返回IP地址給瀏覽器
- 瀏覽器拿到IP地址去訪問服務器,返回響應
- 服務器返回給我們的響應數據:html / css / js / jpg......
1.2、實際原理
一個請求只能對應一個數據包(文件)
2、http協議和https協議
2.1、http協議(超文本傳輸協議)
- 超文本:不僅僅限于文本,還包括圖片、音頻、視頻。
- 傳輸協議:指使用共用約定的固定格式來傳遞轉換成字符串的超文本內容。
2.1.1、作用
- 規定了服務器和客戶端互相通信的規則。
2.1.2、http請求/響應的步驟
- 客戶端連接到web服務器
- 發送http請求
- 服務器接受請求返回響應
- 釋放連接tcp連接
- 客戶端解析html內容
2.1.3、請求頭
請求方式:get? 和? ?post
get:向服務器要資源
post:向服務器提交資源
- User-Agent:模擬正常用戶
- cookie:登錄保持
- referer:當前這一次請求時由哪個請求過來的
抓包得到的響應內容才是判斷依據,elements中的源碼是渲染之后的源碼,這個不能作為判斷標準。
2.1.4、字符串編碼解碼
編碼? ? ? ? -- encode()
字符串轉換成二進制字符串? ? ? ? str 轉換成 bytes
解碼? ? ? ? -- decode()
二進制字符串轉換成字符串? ? ? ? bytes 轉換成 str
三、requests庫的介紹
1、requests基本使用
requests模塊作用:發送http請求,獲取響應數據。
requests模塊式第三方模塊,需要安裝:
1.1、安裝命令:? ? ? ? --? ? pip install requests
1.2、基本使用:
import requests# 目標url
url = 'https://www.baidu.com'# 向目標url發送get請求
response = requests.get(url)# 打印響應內容#將其編碼設置為UTF-8
response.encoding = 'utf-8'print(response.text)# print(response.content.decode()) 默認UTF-8解碼
使用requests庫保存圖片:
import requests# 確定url
url = 'https://img0.baidu.com/it/u=3225468693,477076843&fm=253&fmt=auto&app=138&f=JPEG?w=1115&h=800'# 發送請求,獲取響應
res = requests.get(url)
print(res.content)# 保存響應
with open('1.jpg', 'wb') as f:f.write(res.content)
1.3、常用的屬性或方法
- response.url? 響應的url。有時候響應的url和請求的url并不一致。
- response.status_code? 響應狀態碼。
- response.request.headers? 響應對應的請求頭。
- response.headers? 響應頭
- response.cookies? 響應的cookie(經過了set-cookie動作。返回cookieJar類型)
1.4、其他屬性
response.text 和 response.content 的區別:
text:? str類型,? requests模塊自定根據http頭部對響應的編碼作出有根據的推測。
content: bytes類型,? 可以通過decode()解碼。
2、用戶代理
請求頭中user-agent字段必不可少,表示客戶端操作系統以及瀏覽器的信息。
示例
import requestsurl = 'https://www.baidu.com/'# 構建請求頭
header = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36'
}# 帶上user-agent發送請求
# headers參數接受字典形式的請求頭,請求頭字段名為key,值為value
response = requests.get(url, headers=header)print(response.content.decode())
添加user-agent的目的是為了讓服務器認為是瀏覽器在發送請求,而不是爬蟲在發送請求
3、URL傳參
user-agent池? ? ? ? --防止反爬
第一種方法:使用user-agent池隨機調用
import random# 隨機調用
UAlist = ['Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36','Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1','Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Mobile Safari/537.36',
]print(random.choice(UAlist))
第二種方法:使用fake_useragent ?可能會出現異常
首先下載fake_useragent:pip install?fake_useragent
from fake_useragent import UserAgent
print(UserAgent().random)
3.1、瀏覽器發送請求的原理
- 構建請求
- 查找緩存(在瀏覽器緩存中尋找有沒有需要查找的資源,如果有的話就攔截請求,返回這一資源的副本,并直接結束請求)
- 準備IP地址和端口
- 等待tcp隊列
- 建立tcp連接
- 發送http請求
瀏覽器會向服務器發送請求行,包括了請求方法,請求url,http協議
3.2、編碼轉譯
- 字符串被當做url提交時會被自動進行url編碼處理
- 輸入? ? ? ? ? ?--字符串? ? ? ?明文
- 發送請求的時候? ? ? ? --%xxx%xxx? ? ? ?密文
from urllib.parse import quote, unquote
# quote() #明文轉密文
# unquote() #密文轉明文
print(quote('參數')) # 輸出:%E5%8F%82%E6%95%B0
print(unquote('%E5%8F%82%E6%95%B0')) # 輸出:參數
3.3、發送帶參數的請求
通過params攜帶參數字典:
- 構建請求參數字典
- 發送請求的時候帶上請求參數字典
import requestsurl = 'https://www.baidu.com/s?'header = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36'
}# 構建請求參數字典
name = input("請輸入關鍵字:")
kw = {'wd': name}# 帶上請求參數發起請求,獲取響應
response = requests.get(url, headers=header, params=kw)
print(response.content.decode())
四、簡單案例
1、獲取單張圖片
示例(網易云):
# 1、導入模塊
import requests# 找到目標url
url = 'https://p1.music.126.net/Y2C3RbZflVZMUuNBkKA-Jg==/109951170607654157.jpg?imageView&quality=89'# 構建請求頭字典
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}# 發送請求,獲取響應
res = requests.get(url, headers=headers)
# res.content是二進制數據# 保存文件
with open('網易云.jpg', 'wb') as f:f.write(res.content)
2、獲取單首歌曲
示例(酷我):
# 1、導入模塊
import requests# 找到對應目標的url
url = 'https://ga-sycdn.kuwo.cn/2941b0d5664d5d39fbcc5d58db543670/67d45eec/resource/pay3_v2/279292599/'# 構建請求頭字典
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}# 發送請求,獲得響應
res = requests.get(url, headers=headers)# 保存文件
with open('酷我.mp3', 'wb') as f:f.write(res.content)
3、獲取單個MV
示例(酷我):
# 導入模塊
import requests# 確定目標url
url = 'https://gd-sycdn.kuwo.cn/6bab1f0b832f4a522593a520edc1abee/67d45553/resource/m3/35/83/2343069577.mp4'# 獲取請求頭字典
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}# 發送請求,獲取響應
res = requests.get(url, headers=headers)# 保存文件
with open('mv.mp4', 'wb') as f:f.write(res.content)
4、獲取單頁貼吧
示例(百度貼吧):
# 導入模塊
import requests# 確定目標url
url = 'https://tieba.baidu.com/f?ie=utf-8&kw=%E5%B0%8F%E6%98%8E&fr=search'# 獲取請求頭字典
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}# 發送請求,獲取響應
res = requests.get(url, headers=headers)# 保存文件
with open('小明.html', 'wb') as f:f.write(res.content)
示例(貼吧翻頁):
# 導入模塊
import requests# 確定目標url
url = 'https://tieba.baidu.com/f?'# 獲取請求頭字典
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}search = input('請輸入搜索內容:')
page = int(input('請輸入要保存的頁數:'))for i in range(page):params = {'kw': search,'pn': i*50}# 發送請求,獲取響應res = requests.get(url, headers=headers, params=params)# 保存文件with open(F'{search}{i+1}.html', 'wb') as f:f.write(res.content)
改為面向對象
# 導入模塊
import requests# 改為面向對象class Tb:def __init__(self):self.url = 'https://tieba.baidu.com/f?'self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'}# 發送請求def send(self, params):res = requests.get(self.url, headers=self.headers, params=params)return res.text# 保存數據def save(self, page, con):with open(f'{page}.html', 'w', encoding='utf-8') as f:f.write(con)def run(self):word = input('請輸入查找信息:')pages = int(input('請輸入頁數:'))for page in range(pages):params = {'kw': word,'pn': page*50}# 循環執行data = self.send(params)self.save(page, data)te = Tb()
te.run()
五、post請求和模擬登錄
1、post請求:登錄注冊,傳輸大文本內容
requests.post(url,data)# data參數接受一個字典
get和post的區別:
- get請求 ?--比較多????????????????????????
- post請求 ?--比較少
- get請求直接向服務器發送請求,獲取響應內容
- poet請求是先給服務器一些數據,然后再獲取響應
- get請求攜帶參數 ? --params
- post請求攜帶參數 ?--data
2、cookie? ? 模擬登錄
# 導入模塊
import requestsurl = 'https://music.163.com/'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36','Cookie': 'NMTID=00OirJp6WmwK2CZ0UsRs0AwIsuCZ24AAAGVlUI2ww; _iuqxldmzr_=32; _ntes_nnid=8acdc47e4ec07cfcc0c3d8a5a7563e2b,1741965900532; _ntes_nuid=8acdc47e4ec07cfcc0c3d8a5a7563e2b; WEVNSM=1.0.0; WNMCID=yzysjc.1741965901512.01.0; WM_TID=uR%2FXeQkMY%2BBEREERQAeWZsNjcExlNr%2Fr; sDeviceId=YD-wk74YKwl8c1BEgVBFVbBkf9FLdSm06BO; ntes_utid=tid._.jwaAVzsxdbJFRkFAAUfDM9YiNEl0ltaU._.0; __snaker__id=HFEZmaht8jsYG5Lq; JSESSIONID-WYYY=D4asd5JMMPTACEfo1h%5CuG3iv1f2kh4UokwaX6EThS3M6N%2BTH2v8RFTnYrueIKW6KK05aXaUMNg4muZNN1HwU6meM4CI%2F3swbc2%5CQ19yJAjnHar08eUxlMd6sZme0mrgWUZ%2B1Yz0lztuFpXI2ftmblBDuXpf%2FbJEy9Y7uRz9ocrPdN83W%3A1742052144561; WM_NI=uvbx63QfSmoh%2B74VnJtzOY3PI8UFru33HLKrWjKUtPOsE%2FJeYNhNhn2AIT1aHmDoEZDHq1GJ5C%2BgGLQobuWHScYDBnqiCBkb4Mh9VgIo%2FS%2B0CJ0ZUgjvDhqdG0OsaO0zUmg%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6eeb3c55e9b939c88ce3dae9a8aa3d15f928a8e87c269fb94adabe766acbcf79bf92af0fea7c3b92ab7aaae99b53993ba9d8eee64e9e9fcb7ed42b8a681bab25c8be89ba7f17ff1ed88adca7a95b685b6f75c8dad8bd0c96f9b92a8afeb66f29f87b5b46b8cb38c90c8528898bfd2c642f79de588c64893b1ae96d64491bd97a5c166b3b78da3ea6af893a8dad56d8bb1e1b4aa3c819600bbd86daaaa8c89f47085f08194e445f4a69b8ee637e2a3; gdxidpyhxdE=OOzg9mY%2FxHuPDnHdx434EhbnKe5iAVw5gopZkA4GbO4xlhAJYlrunqeeT3mnVYsjaLgbMuXlm9Z3QdBpG2JLgex1w9OCqOm5ftHtqC0wvLOZbX6SJdnRKwjOcitbT9ViOWEItod3TyULCDOK%5Cy%5CuEvaAqdcv%2FPGk5Ax%5C26UMJI8dPzt6%3A1742051249437; __csrf=5b42a43d68078759426489b0b38b1550; MUSIC_U=00D6018410AF7F96CDC71B00BDBA2443074C93CB0859C0894B62EB44734CB09C8F339E40951BECD0A20BF971729D9E195D51057ED0B5601D9EB8504B44BA59190FC07E793A37F266D6B8FDF3CDA161416292E1690844821EBEE9B31E9B9EECC551AAA85ED5BEC21FC171CD3907BEE0F88BE58ABC25EBEE9FAFBCB8821C649C99B7AFE8D2C622FA851CD0096BB46B0A869688E1038BA3034E434D4EDD76242A23743EA0FAF138DE54513B4AFD4756238A5B03471FC7B5F4B5748D142991DB96CA7A9AD4AF0CAD55462359561BA5D3164128F00508A709CF4CCF0407BE84A8A25945F2DBCB4614F4AEB64E740E93E56FCD68291F57E410DC0260BEFA6BD303378F0CB856081EAD6433FCBA395F144059BF3D18D3CBAAEFB267307A0683684042C4558E9965D2379DC9B92EBEDB41563C1C7F3B59114880CD15E586C57504BDEEB7F61CE50DACC1C5DED2C6C42205A8E360E6A8BB3CF69469EF9712A6A35972CB79BE; ntes_kaola_ad=1'
}# 發送請求
res = requests.get(url, headers=headers)
print(res.text)
3、post請求舉例
示例(金山翻譯):
# 導入模塊
import requests
import jsonurl = 'https://ifanyi.iciba.com/index.php?c=trans'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}word = input('請輸入你要翻譯的內容:')# 構建data參數字典
post_data = {'from': 'zh','to': 'en','q': word
}res = requests.post(url, headers=headers, data=post_data)
# print(res.text)# 解析數據
# 將json數據轉換為Python字典
dic = json.loads(res.text)
print(dic['out'])
4、session
requests模塊中的session類能夠自動處理發送請求獲取響應過程中所產生的cookie,進而達到狀態保持的目的。(自動處理cookie,即下一次請求會帶上前一次的cookie。)
session = requests.session() #實例化session對象
res = session.post(url,data=data)使用session訪問登錄以后的頁面
session.get(url.text)
- 1、對訪問登錄后才能訪問的頁面去進行抓包
- 2、確定登錄請求的url地址,請求方法和所需的參數
- 3、確定登錄才能訪問的頁面url和請求方法
- 4、利用requests.session完成代碼
5、cookie池
user-agent池:短時間內多次發出請求,盡量每一次的請求都用不同的用戶代理。
cookie池:每一個cookie就代表一個賬號。
cookie有有效期,session不用擔心有效期的問題。
cookie跟session的區別:
- cookie數據放在瀏覽器中,session數據放在服務器中。
- cookie不安全,別人可以分析存放在本地的cooker并進行cookie欺騙,考慮到安全應當使用session。
- session會在一定時間內保存在服務器上,考慮到減輕服務器性能方面,應當使用cookie。
- 可以考慮將登錄信息等重要信息存放在session,其他信息如果需保留,可以存放在cookie中。