背景
未系统学习过python爬虫,但了解一些web原理,即前端js等知识,以及post,put等方法
某个晚上瞥到视频,于是心血来潮跟着视频实操了一个微型小爬虫,大佬轻喷
B站原视频:用Python下载无水印快手上的小姐姐视频
一. 数据来源分析:
快手动态页面
并非其中所有数据都在这个页面当中,而是通过一个object去加载,这是前端的知识
请求 图片 文字 需求 包括所有这些我们需要的东西,都在这个network中,你可以把它就看成一个抓包工具
二. python代码实现过程:
- 实现网络请求
- 解析数据(获取视频地址)
- 向视频地址发送网络请求
- 保存视频
三. 实操代码:
导入requests模块,能够帮助我们发送网络请求
"""
抓取快手视频,实现四步:
1. 实现网络请求
2. 解析数据
3. 向视频网址发送网络请求
4. 保存视频
"""
import json
import requests
# 1. 发送网络请求
# get post
url = 'https://www.kuaishou.com/graphql'
# header请求头 用来伪装python代码,防止被识别出来是一个python爬虫程序
headers = {
'content-type': 'application/json',
'Cookie': 'kpf=PC_WEB; kpn=KUAISHOU_VISION; clientid=3; did=web_5479344c1db853344353bd9543cb1c70',
'Host': 'www.kuaishou.com',
'Origin': 'https://www.kuaishou.com',
'Referer': 'https://www.kuaishou.com/search/video?searchKey=%E9%BB%91%E4%B8%9D%E5%B0%8F%E5%A7%90%E5%A7%90',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
}
# 查询参数(data此时是一个字典,但网站需要的是json)
data = {
'operationName': "visionSearchPhoto",
'query': "query visionSearchPhoto($keyword: String, $pcursor: String, $searchSessionId: String, $page: String, $webPageArea: String) {\n visionSearchPhoto(keyword: $keyword, pcursor: $pcursor, searchSessionId: $searchSessionId, page: $page, webPageArea: $webPageArea) {\n result\n llsid\n webPageArea\n feeds {\n type\n author {\n id\n name\n following\n headerUrl\n headerUrls {\n cdn\n url\n __typename\n }\n __typename\n }\n tags {\n type\n name\n __typename\n }\n photo {\n id\n duration\n caption\n likeCount\n realLikeCount\n coverUrl\n photoUrl\n liked\n timestamp\n expTag\n coverUrls {\n cdn\n url\n __typename\n }\n photoUrls {\n cdn\n url\n __typename\n }\n animatedCoverUrl\n stereoType\n videoRatio\n __typename\n }\n canAddComment\n currentPcursor\n llsid\n status\n __typename\n }\n searchSessionId\n pcursor\n aladdinBanner {\n imgUrl\n link\n __typename\n }\n __typename\n }\n}\n",
'variables': {'keyword': "高街女帝", 'pcursor': "", 'page': "search"}
}
data = json.dumps(data)
response = requests.post(url, data=data, headers=headers)
data_list = response.json()['data']['visionSearchPhoto']['feeds']
# []: 列表
for feed in data_list:
title = feed['photo']['caption']
url_1 = feed['photo']['photoUrl']
print(title)
# 3. 向视频地址 发送网络请求
resp = requests.get(url_1).content
try:
with open('video\\' + title + '.mp4', mode='wb') as f:
f.write(resp)
except IOError:
print('出现\\n错误!')
print(title, '爬取成功!')
最终实现效果:
过程中可能的报错:
可能会需要人机验证进入快手页面后才能爬
“data_list = response.json()[‘data’][‘visionSearchPhoto’][‘feeds’] TypeError: ‘NoneType’ object is not subscriptable”
即:data中无法检测到feeds属性
原因
:快手网站防爬虫防惯了,你要先进行人机验证进入页面后才能爬
所以先登录网站,在以已经进行完人机验证,登录完网站的主机来爬,
才不会被拦截,得到的data数据才不是登录界面的data,而是视频界面的data
(注:如果按照原视频当中的代码敲,可能出现
只成功爬取了几个视频,随后程序终止,控制台输出信息:
C:\Users\31219\Documents\PycharmProjects\pythonProject1\venv\Scripts\python.exe C:/Users/31219/Documents/PycharmProjects/pythonProject1/快手.py
快a你的好朋友一起看吧 @快手热点(O3xddgkd5fav5if9) #搞笑视频 #搞笑 爬取成功!
Traceback (most recent call last):
File C:/Users/31219/Documents/PycharmProjects/pythonProject1/快手.py, line 40, in module
with open(video\\ + title + .mp4, mode=wb) as f:
OSError: 【Errno 22】 Invalid argument: video\\据说打出“我要”就知道你想干嘛啦~\n #快手颜值.mp4
Process finished with exit code 1
为什么会出现invalid argument?
因为 据说打出“我要”就知道你想干嘛啦~\n #快手颜值.mp4
视频对象的title = feed[‘photo’][‘caption’]属性(即标题属性)中,含有’/n’字符,导致读取时只能读取到:据说打出“我要”就知道你想干嘛啦~,
为了防止此类特殊视频标题导致的爬虫进行终止,我在本文章中的程序中加入了python的异常处理机制try…except…,一旦出错就跳过该视频继续爬取.)