网页源代码抓取工具( 说起B站的反扒机制(一)太严格(组图))
优采云 发布时间: 2022-01-06 20:08网页源代码抓取工具(
说起B站的反扒机制(一)太严格(组图))
说到B站,大家都知道。B站的反接机机制不是很严格,所以今天就给大家说说我能想到的几种方式。目前我大概想到了三种方式:
那我就一一给大家介绍我的方法!
分析及主要代码:
既然确定了方法一模拟手机端请求,那么我们直接开始分析:
抓了链接,找了半天,也没找到有用的信息,于是直接去查网页源码:
仔细查看源代码后,发现了如上所示的信息。源代码中加载了视频的 MP4 链接和视频名称。
因为这个信息存储在标签中,虽然可以提取所有内容,然后转换为JSON格式进行提取,但这有点麻烦。我们直接用正则表达式提取:
代码
class BiLiBiLi_phone():
def __init__(self,s_url):
self.url=s_url
self.headers={
'origin': 'https://m.bilibili.com',
'referer': self.url,
'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N)'
}
def bili_Download(self):
r = requests.get(self.url, proxies=proxy, headers=self.headers)
video_name=re.findall(',"title":"(.*?)","pubdate":', r.text)[0]
if video_name == '':
video_name = int(random.random() * 2 * 1000)
if len(str(video_name)) > 20:
video_name = video_name[:20]
video_url = re.findall(',"url":"(.*?)","backup_url"', r.text)[0].encode('utf-8').decode('unicode_escape')
r=requests.get(video_url,proxies=proxy,headers=self.headers)
with open(path+video_name+'.mp4','wb')as f:
f.write(r.content)
print("【BiLiBiLi】: {} 下载完成!".format(video_name))
关于代码的一些说明:
*敏*感*词*字体前的代码是正则表达式的基本操作,*敏*感*词*字体的原因是:
从源代码中提取的链接是:
网址:?\ u002F \\ u002Fupgcxcode \ u002F10 \ u002F14 \ u002F230501410 \ u002F230501410-1-1 6. MP4 E = ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM =&uipk = 5&NBS = 1&期限= 1601216024&根= playurl&OS = kodobv&OI = 1971851232 & trid = fcde238782674b78bf4425427c2a9ea3h & 平台 = html5 & upsig = b98cc40700e7f05e614acf0acbd9b671 & uparams = e,suidepk040,800,800,2000,800,000,000,000,000,000,000,800,000,000,000,000,800,000,000,000,000,000,000,000,000,000,000,000,000,050
该链接收录大量 \u002F 字段。这是因为源代码加载了转换为Unicode编码的链接,所以需要进行编码转换。
分析及主要代码:
对于方法二,我们首先需要找到第三方网站来解析视频,然后打包整个过程。
不同的网站有不同的分析方法。我只会写一个网站我随机选择的。清晰度还行。
这个网站之间的特殊性:当输入链接是:
出现以下错误时
所以你需要去掉下面的一些信息!
把准备好的链接放到分析网站中,得到如下信息:
由于网站的特殊性,如果选择MP4文件,有时视频会被分成多个,所以这里我主要选择FLV文件。
我们可以很清楚的看到这个接口返回的内容是一些属于HTML标签的信息。我们不在这里编写代码来进行清晰选择。需要的可以自己写,直接选择清晰度最好的来分析。.
代码
这是为了防止这个B站视频分析服务网站被滥用。这里我隐藏了分辨率网站。如果你想使用这个解析服务的地址,可以私信给我。
这种分析网站的特点之一是,知道的人越多,失败的速度就越快。
希望它能活得尽可能长。
class BiLiBiLi_api():
def __init__(self, s_url):
self.url = s_url.split('?')[0]
self.header1 = {
'Host': 'www.****.com',
'Origin': 'http://www.****.com',
'Referer': quote('http://www.****.com/video?url={}&page=video&submit=视频下载'.format(self.url)),
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.63'
}
self.data = {
'url': self.url,
'format': 'flv',
'from': 'parse',
'retry': '1'
}
self.header2 = {
'origin': 'https://www.bilibili.com/',
'referer': self.url,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.63'
}
def BL_api_Download(self):
r = requests.post('http://www.****.com/parse', proxies=proxy, data=self.data, headers=self.header1)
video_name = re.findall('data-clipboard-text="(.*?)"', r.json()['msg'])[0]
video_url = re.findall('href="(.*?)"', r.json()['msg'])[0].replace('amp;', '')
r1 = requests.get(video_url, proxies=proxy, headers=self.header2)
with open(path + video_name + '.flv', 'wb')as f:
f.write(r1.content)
print("【BiLiBiLi】: {} 下载完成!".format(video_name))
关于代码的一些说明:
为什么要把请求头分别写成两个:
不用说,第一个请求头所需要的信息是正常操作。当第二个请求头需要信息的时候,因为这个网站解析的视频链接是B站的原链接,你必须带上B站信息的请求头下载,否则服务器会拒绝我们的访问。
在上面解析网站的过程中,我们还记得请求解析链接后,我们还需要选择视频文件的格式,才能获取视频的链接,当我们选择了格式,我们将再次检查原件。链接到请求,并且会携带固定格式的数据数据。
为什么需要进行编码转换:
网站 就是这样,不改代码,会报错,呵呵。
前面说了,没有标*敏*感*词*的部分还是基本操作,就是使用正则表达式提取信息,对于标*敏*感*词*的部分,这是因为解析的链接中收录了HTML传输字符:
和
方法三
写...(遇到了点小麻烦!)
所有源代码
import random
import re
from urllib.parse import quote
import requests
url = 'https://ip.jiangxianli.com/api/proxy_ip'
r = requests.get(url)
proxy = {'HTTP': 'http://' + r.json()['data']['ip'] + ':' + r.json()['data']['port']}
print(proxy)
path = 'C:/Users/Jackson-art/Desktop/'
class BiLiBiLi_phone():
def __init__(self, s_url):
self.url = s_url
self.headers = {
'origin': 'https://m.bilibili.com',
'referer': self.url,
'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N)'
}
def bili_Download(self):
r = requests.get(self.url, proxies=proxy, headers=self.headers)
video_name = re.findall(',"title":"(.*?)","pubdate":', r.text)[0]
if video_name == '':
video_name = int(random.random() * 2 * 1000)
if len(str(video_name)) > 20:
video_name = video_name[:20]
video_url = re.findall(',"url":"(.*?)","backup_url"', r.text)[0].encode('utf-8').decode('unicode_escape')
r = requests.get(video_url, proxies=proxy, headers=self.headers)
with open(path + video_name + '.mp4', 'wb')as f:
f.write(r.content)
print("【BiLiBiLi】: {} 下载完成!".format(video_name))
class BiLiBiLi_api():
def __init__(self, s_url):
self.url = s_url.split('?')[0]
self.header1 = {
'Host': 'www.****.com',
'Origin': 'http://www.****.com',
'Referer': quote('http://www.****.com/video?url={}&page=video&submit=视频下载'.format(self.url)),
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.63'
}
self.data = {
'url': self.url,
'format': 'flv',
'from': 'parse',
'retry': '1'
}
self.header2 = {
'origin': 'https://www.bilibili.com/',
'referer': self.url,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.63'
}
def BL_api_Download(self):
r = requests.post('http://www.****.com/parse', proxies=proxy, data=self.data, headers=self.header1)
video_name = re.findall('data-clipboard-text="(.*?)"', r.json()['msg'])[0]
video_url = re.findall('href="(.*?)"', r.json()['msg'])[0].replace('amp;', '')
r1 = requests.get(video_url, proxies=proxy, headers=self.header2)
with open(path + video_name + '.flv', 'wb')as f:
f.write(r1.content)
print("【BiLiBiLi】: {} 下载完成!".format(video_name))
def user_ui():
print('*' * 10 + '\t BiLiBiLi视频下载\t' + '*' * 10)
print('*' * 5 + "\t\tAuthor: 高智商白痴\t\t" + '*' * 5)
share_url = input('请输入分享链接: ')
choice = int(input("1、模拟手机端下载 2、调用接口下载 3、直接下载\n选择下载方式:"))
if choice == 1:
BiLiBiLi_phone(share_url).bili_Download()
if choice == 2:
BiLiBiLi_api(share_url).BL_api_Download()
if choice == 3:
print("编写中。。。")
if __name__ == '__main__':
user_ui()
大好处
虽然这篇博文还没有写完,但还是迫不及待的给大家分享了很多西部:B站壁纸。
其实B站有个公众号,里面全是2233少女的一些壁纸,呵呵~
你学会了吗?