手把手带你用Python爬取反爬策略的网站
由于网站对cookie的部分更新,所以需要对程序做略微修改才能使用。
session.cookies = requests.sessions.merge_cookies(session.cookies, dict(zzz0821='1'))
这一行中的 cookie 参数 zzz0821
被网站管理员更新为了 fb1012
,短期内应该没有变化,长期内整体算法应该没有变化,改变结果为:
session.cookies = requests.sessions.merge_cookies(session.cookies, dict(fb1012='1'))
其他地方保持不变。
首先我习惯性选择先百度看看有没有其他方法,无意间看到有个库
you-get
很符合我胃口,对常见的 bilibili 等40多个网站都有较好的自动爬取视频支持,使用命令行you-get 你要爬的网址
就能自动把网页上能下载的视频和图片保存下来,分析出的画质在 高清1080P(默认下载),或者使用you-get -i 你要爬的网址
来分析视频不同清晰度,以选择想要的清晰度下载。不过肯定没有第三方提供的视频地址获取好,毕竟我看下载大小,第三方提供的视频地址获取应该给的是最高画质。
实际上,爬 bilibili 和爬全民K歌没有什么区别,都在网页底部的script里面有数据可以查看,不过数据中的网址不能直接在浏览器里浏览,必须要加上 referer 参数才能访问到数据。
这样就能下载视频大小最大(画质最好)的那个视频了,和you-get默认下载的视频画质一致(一般情况),但一样比不过第三方提供的视频地址获取网站给出的画质,如果对画质要求不高的使用
you-get
或本程序,毕竟第三方网站算法在未来可能会更新(好像B站算法也有可能会更新)。
# import sys
# from you_get import common
# sys.argv = ['you-get', '你要下载的视频地址', '-i'] # 分析视频信息
# common.main()
# sys.argv = ['you-get', '你要下载的视频地址'] # 下载默认视频信息
# common.main()
import json
import time
import requests
from bs4 import BeautifulSoup
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"
}
def get_video_url(url):
while 1:
res = requests.get(url)
if res.ok:
soup = BeautifulSoup(res.text, 'lxml')
for script in soup.find_all('script'):
if 'window.__playinfo__' in script.text:
text = script.text
return soup.find('span', class_='tit').text, json.loads(text[text.find('{'): text.rfind('}') + 1])
else:
time.sleep(1)
urls = """
""".strip('\n')
for page_url in urls.split('\n'):
name, result = get_video_url(page_url)
# 选出最大大小的视频
urls = [_['baseUrl'] for _ in result['data']['dash']['video']]
end_choice = (0, '')
for u in urls:
headers['Referer'] = page_url
response = requests.get(u, headers=headers, stream=True)
if int(response.headers['Content-Length']) > end_choice[0]:
end_choice = (int(response.headers['Content-Length']), u)
print(f'{name} 大小:{end_choice[0]}')
response = requests.get(end_choice[1], headers=headers, stream=True)
open(f'bilibili_videos/{name}.mp4', 'wb').write(response.content)
print(f'{name} 下载完毕!')
从简单中发现不简单。