经过昨天的学习,现在我们就可以完成一些简单的实战案例。
1. 一首歌曲的爬取
目标 url : https://y.qq.com/n/ryqq/player
打开该网页 右键检查 选择 清空数据后再刷新网页
进行抓包
数据很多 因为是歌曲我们猜测 想要的数据可能在 Media
中 所以直接选择 Media
有一个这样的 数据 我们复制它所对应的Url 用浏览器打开
打开后会自动播放 显然 这就是我们想要的歌曲 接下来我们用代码爬取这首歌 保存到本地。
import requests
if __name__ == '__main__':
# 1.确认目标的url
url_ = "https://dl.stream.qqmusic.qq.com/C400001JSAfL0ugBUp.m4a?guid=779222106&vkey=CB14F1638005DB0B502FDA7A10B297248DDD269191D0A257FC23F1FAEE86CB21436A40C760485F520322420F190E5EEFBD9FA85512B2050C&uin=2023496672&fromtag=120032"
# 设置用户代理
headers_ = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
}
# 2.发送请求
response_ = requests.get(url_, headers=headers_)
bytes_data = response_.content
# 4.写入
with open('忘川彼岸.mp3', 'wb') as f:
f.write(bytes_data)
[[注]
]: 只能爬取非Vip的歌曲 有Vip账户可以爬取Vip歌曲(后面会讲到)
2. 单个MV的爬取
目标 URL :https://y.qq.com/n/ryqq/mv/003pcd2d2cpZiK
经过抓包分析 与上个案例有所不同 我们想要的数据不在 Media中
但是在 Fetch/XHR
中 随着MV的播放有一个数据一直出现 我们猜测它可能就是我们想要的MV数据
输入到浏览器发现 有个文件在下载,下载成功后打开播放 显然是我们要爬取的MV
接下来我们通过代码来实现单个MV的爬取
"""
单个MV
"""
import requests
if __name__ == '__main__':
url_ = "https://apd-9a0f1710c7cef13cea92d8ac94730157.v.smtcdns.com/mv.music.tc.qq.com/AdAutG7huZtb8UBwR5YbSrWZ7m5estdSoT065875s74U/30BBBFF77B7FCAC77C15663E8BBEA0B3126A7D51960C4272A9007E75E4AD37556D6B945728E49A1DD771DC432A9BB0ABZZqqmusic_default/qmmv_0b53qmacyaaap4adhcaejrsvjayafsbqalca.f9944.ts"
# 设置用户代理
headers_ = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
}
# 2.发送请求
response_ = requests.get(url_, headers=headers_)
bytes_data = response_.content
# 4.写入
with open('그냥 그렇게 됐어.mp4', 'wb') as f:
f.write(bytes_data)
3. 贴吧案例
3. 1 单页贴吧案例
目标 URL :https://tieba.baidu.com/index.html
我们输入健身进行搜索
通过抓包分析 想要的单页就是这个数据所对应的 URL:
https://tieba.baidu.com/f?ie=utf-8&kw=%E5%81%A5%E8%BA%AB&fr=search
%E5%81%A5%E8%BA%AB 这个又是什么呢? 我们之前学过url的转义
from urllib.parse import unquote
print(unquote("%E5%81%A5%E8%BA%AB"))
转为明文 发现就是我们输入的关键字 健身
这个 url 太长了 我们试着简化一下
https://tieba.baidu.com/f?&kw=健身
接下来我们通过url传参 来实现不同关键字的搜索 如下代码:
"""
单页贴吧数据
"""
import requests
if __name__ == '__main__':
data_ = input('请输入你想爬取的贴吧:')
# 1.确认目标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/98.0.4758.82 Safari/537.36"
}
params_ = {
'kw':data_
}
# 2.发送网络请求,得到响应对象
response_ = requests.get(url_, headers=headers_,params=params_)
str_data = response_.content.decode()
# 4.保存
with open(f'{data_}.html','w',encoding="utf-8") as f:
f.write(str_data)
3. 2 多页贴吧案例
通过观察发现
只需要 传入pn
参数来控制爬取的页数,就能实现翻页
贴吧多页爬取 1个url >> 一个资源 多个url >> 多个资源
简单 >> url有规律可循第1页的url: https://tieba.baidu.com/f?kw=%E7%BE%8E%E9%A3%9F&pn=0
第一页一般都不会显示 050 第2页的url:
https://tieba.baidu.com/f?kw=%E7%BE%8E%E9%A3%9F&pn=50 150 第3页的url:
https://tieba.baidu.com/f?kw=%E7%BE%8E%E9%A3%9F&pn=100 250 第4页的url:
https://tieba.baidu.com/f?kw=%E7%BE%8E%E9%A3%9F&pn=150 350想法:使用for循环就可以使用url参数的规律变化,实现翻页
import requests
if __name__ == '__main__':
data_ = input('请输入你要搜索的贴吧内容:')
pages_ = int(input('请输入你要爬取的页数:'))
for i in range(pages_): # range(0,10) 0 1 2 3 4 5 6 7 8 9
# 确认目标的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/98.0.4758.82 Safari/537.36"
}
# 设置url的参数
params_ = {
"kw": data_,
"pn": i * 50
}
# 发送网络请求,得到响应
response_ = requests.get(url_, headers=headers_, params=params_)
str_data = response_.content.decode()
with open(f'{data_}_{i + 1}.html', 'w', encoding="utf-8") as f:
f.write(str_data)
3. 3 使用面向对象完成贴吧翻页爬取
"""
面向对象贴吧案例
"""
import requests
class TieBa:
# 初始化init方法 >> 是不是只要创建对象,那么该方法就会被执行
def __init__(self):
self.url_ = "https://tieba.baidu.com/f"
self.headers_ = {
"Cookie": "BAIDUID=AE16EE27343B25D5DBD37EE0580AA351:FG=1; PSTM=1627283384; BIDUPSID=E87874A693DB88716FD0E61C71073BCC; __yjs_duid=1_be57b8bfc8bffacdf8573b0697073d511627307214203; bdshare_firstime=1632463635044; BCLID_BFESS=8335763491484922959; BDSFRCVID_BFESS=eTtOJeC62lglgzQHPXGJIGgdQpyGp_JTH6aoMw3AQf0BsIvX45xeEG0PsM8g0KAb9HVXogKKLmOTHpKF_2uxOjjg8UtVJeC6EG0Ptf8g0f5; H_BDCLCKID_SF_BFESS=tb4q_KDKtIt3fP36q46EhRtJ5f6tet6-bn3--PbvWJ5TMCo1bPvJ2l_n0b7xBfcx5KnIQPTT-U7kShPC-tnY5TtF0fDj3JJAbH-J_4nH3l02V-OEe-t2yU_Vet7pXPRMW23rWl7mWPJvsxA45J7cM4IseboJLfT-0bc4KKJxbnLWeIJIjj6jK4JKjatOtT5P; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; MCITY=-%3A; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; delPer=0; PSINO=6; NO_UNAME=1; st_key_id=17; 1994866108_FRSVideoUploadTip=1; video_bubble1994866108=1; BAIDU_WISE_UID=wapp_1644499211345_725; USER_JUMP=-1; baidu_broswer_setup_=0; BDRCVFR[abe9uUBlp-C]=mbxnW11j9Dfmh7GuZR8mvqV; BDUSS=pxWE5Yd1psSmdlTTF2Z2o1TGZRVDFtNzBXN09GejZaV3YtfkxzOFE2T3RwaXhpRUFBQUFBJCQAAAAAAAAAAAEAAABwurKIsq6-9E5vMTMyMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK0ZBWKtGQViNX; BDUSS_BFESS=pxWE5Yd1psSmdlTTF2Z2o1TGZRVDFtNzBXN09GejZaV3YtfkxzOFE2T3RwaXhpRUFBQUFBJCQAAAAAAAAAAAEAAABwurKIsq6-9E5vMTMyMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK0ZBWKtGQViNX; H_PS_PSSID=35413_35104_35833_35488_35777_34584_35491_35871_35245_35326_26350_35885_35878_35746; BA_HECTOR=8h85aga4ah05a021a11h0a6dg0r; STOKEN=9790f32910ede869949affe26b33557bb904e96a6f567dcf4946a1fb8aa4d846; tb_as_data=97bbd0d1899e0c915fe74e1b9b0d5da94e2f6c6834264827c2cd221546df751d255cd294d5eb9bd85c3def00f0ba85ebe0ce365dcfba5ca3d29c3bb3660881dcf09aa24443f69c701bc062314968b19b0110c034855ea328174c472134eb01b9d2a642d8222074e2bbfed65f870f2a97; Hm_lvt_98b9d8c2fd6608d564bf2ac2ae642948=1644497105,1644501434; Hm_lpvt_98b9d8c2fd6608d564bf2ac2ae642948=1644501434; ab_sr=1.0.1_YTc4NDJiZGZhYjczM2JkZGY0OGVmMWE5NzFjM2JhYTUxOTliODVjZDRiMjA1ZDRjMzAxN2I5NmQwZDdlMWNmMTk2NjMwYTE3OTI2MGY0MWNlNmM2MmYzZDllZmNjMDZhMjAyNjYyOTBmZTBlYzBjMDUyMDNiNDE1ZjRjODg5YWU2MmEwODRhMjA1ZWMzZGRkNmU2MTc4YzEwYmQzNDQ4YmIxYTNhMTU1Yjc3OWM4NGExNWU3YjRhNGYzZGQwNGQ1; st_data=6bd2a14a5533fe7314d79e237d2431031ab4970b6b24cd77d40e97604c09fb09ec573e45b1034a3a242234f954751d42f0316d788eee666aeb165c59b9f7fba2a7a43427705adfa6d1631663c653e9d4aa784d44c42fc6ac1e0ad714d1dc5b3a; st_sign=e8e927b6",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
}
# 发送请求,得到响应数据
def send_request(self,params_):
response_ = requests.get(self.url_,headers=self.headers_,params=params_)
str_data = response_.content.decode()
return str_data
# 解析数据
# 保存数据 页数 保存的内容 标题
def save_data(self,page,str_data,data_): # 保存就需要接受数据
with open(f'{data_}_{page+1}.html','w',encoding="utf-8") as f:
f.write(str_data)
# 调度方法(用来调用其它的方法组合在一起使用)
def run(self):
# 确认爬取什么贴吧以及页数
data_ = input('请输入你要搜索的贴吧内容:') # 美食
pages_ = int(input('请输入你要爬取的页数:'))
for page in range(pages_):
params_ = {
"kw": data_,
"pn": page * 50
}
# 调用 发送请求的方法
str_data = self.send_request(params_)
# 保存数据
self.save_data(page,str_data,data_)
if __name__ == '__main__':
tieba_ = TieBa()
tieba_.run()