Skip to content

Latest commit

 

History

History
594 lines (327 loc) · 16.5 KB

爬取短视频.md

File metadata and controls

594 lines (327 loc) · 16.5 KB
typora-root-url typora-copy-images-to
爬虫\images
爬虫\images

爬取短视频

静态网页:request请求的就是当前url

动态网页:需要进行抓包处理。

判断条件

使用查看网页源代码:页面当中的数据在网页源代码中有,那就是静态的,否则的就是需要动态抓包处理。

好看视频

参考网站

教学

https://www.bilibili.com/video/BV1fJ411J719?from=search&seid=15740661422866602053

步骤

看是否动态网页 检查源代码和网页有些话是否出现,出现在源代码中就是静态页面

image-20210202221425603

判断哪个包传的。

因此我们需要抓包,包地址和你正常访问地址很有可能不一样。

image-20210202221623402

微博好像是静态页面

单页面

对于请求头

User-Agent

image-20210202222341417

cookie

image-20210202222516343

image-20210202223720804

数据格式是unicode编码

数据解析

视频数据需要:获得title

image-20210202224934898

得到的json数据

image-20210202225111592

如何获得视频尾缀

直接拼接

import requests
import json
base_url='https://haokan.baidu.com/videoui/api/videorec?tab=gaoxiao&act=pcFeed&pd=pc&num=20&shuaxin_id=1612276740204'
headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36',
    'Cookie': 'BIDUPSID=8303CDB62079598D55280B09241EC6A5; PSTM=1609205633; BAIDUID=8303CDB62079598D785D47E1C310AF5F:FG=1; ab_jid=e8f37dcb0d84ebde578eaeb4c81de8c0ef8e; ab_jid_BFESS=e8f37dcb0d84ebde578eaeb4c81de8c0ef8e; BAIDUID_BFESS=8303CDB62079598D785D47E1C310AF5F:FG=1; BDUSS=VkM29seVBtNW9BY35hdk80YzV4MXIyaS1UOWJPMnFnU2lmZ0tjak05TlZreDVnRVFBQUFBJCQAAAAAAAAAAAEAAADGgNJFysXLrsH3xOqy0NK5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUG919VBvdfTE; BDUSS_BFESS=VkM29seVBtNW9BY35hdk80YzV4MXIyaS1UOWJPMnFnU2lmZ0tjak05TlZreDVnRVFBQUFBJCQAAAAAAAAAAAEAAADGgNJFysXLrsH3xOqy0NK5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUG919VBvdfTE; H_PS_PSSID=33425_33581_33257_33273_31660_33594_33339_26350_33264; BA_HECTOR=85010120a4058h81331g1ilep0r; __yjs_duid=1_f17eb43300edc3f1cb0b26e84be486ad1612274351261; ab_sr=1.0.0_M2NkNDA5MTRmZWM0MDlmMzczMmQ2MmNiM2QxZGE2ZDcwYWE1MWE5MmM5YmY1YTc5YTFmYWMxYjdlNzNiM2MzYmRhYjg4M2MzMjM4ZTc1YjQ0NGFmYjliMjk4ZDU0YWM4'
}
# 发送请求
response = requests.get(base_url, headers=headers)
data = response.text
# print(data)
# 数据转换 把json字符串转换为python可以交换的类型
import json
json_data = json.loads(data)

# 数据解析  看你需要什么数据
# 一层层获得数据 网站json.cn可视化json
#  解析title,视频数据url类型(猜测)
data_list = json_data['data']['response']['videos']
# 遍历列表
for data_item in data_list:
    # print(data_item)
    #  视频文件名字 需要自己加尾缀
    video_title=data_item['title']+'.mp4' 
    #  视频存在位置
    video_Url = data_item['play_url']
    # print(video_title)
    print('正在下载',video_title)
    #  再次发送具体视频URL地址 得到的是二进制数据,需要后面加上一个content
    video_data = requests.get(video_Url,headers=headers).content

    #  保存在文件夹videos,wb方式写入,二进制方式
    with open('videos\\'+video_title,'wb') as f:
        f.write(video_data)
        print('下载完成...\n')

以上是单页面爬取

注意:

.content是是因为获得视频url得到的数据(图像,音频,视频)。

requests的请求返回的是一个对象

.text是文本数据

多页面爬取

如何实行翻页

看着network,你往下翻,看数据包是否变化

image-20210202231904925

image-20210202231932375

这是参数变化

这里翻页的包的请求参数没有变化。

**这是相同的URL的地址,返回的数据不一样。**这里是没有变化,需要注意的点。

有些是会变化的。

所以构建for循环就行了

image-20210202232736552

因为这个URL是没有变化的。

注意

b站不可以,因为是有参数加密。

b站视频

参考视频

https://www.bilibili.com/video/BV1Fy4y1D7XS

网页源代码有些东西有,这是静态页面的吗?

这是视频流数据

b站视频画面和音频数据是分开的,意思就是视频时无声的。

它是在playinfo找到baseurl中找到视频地址。

但是没有声音。

微博

https://weibo.com/tv/show

这个类似于好看视频

爆米花视频

只是实现单页面模式,但是里面post_form中的

image-20210203205339810

需要自己调一次获得的视频个数,但是这个搞笑区效果不好,暂时不打算继续下去,但是代码已经成功实现能成功爬取视频,只是多页面等操作看后面搞不搞把。

跟好看视频是一样的模式

https://www.baomihua.com/funny

image-20210203151115255

地址在这里面的link,然后点击之后跳转到另外一个页面然后还可以获得视频url地址。

image-20210203151329631

然后就得到地址。

上面是post请求

https://www.bilibili.com/video/BV1Ub411B7aM?from=search&seid=739901640749625509

它前面得到Playid,的后面是后一个链接需要post的数据。

image-20210203202616090

解析url得到后面的参数

最后一个得到json得到mp4

image-20210203203126181

IP代理池

第一次尝试:

参考1:89免费代理已模仿成功

参考2:没实现

这个没实现,但感觉比第二个可靠,使用了数据库

b站教你构建快代理代理池

实际运用到代理中出现的问题

image-20210203222814234

解决办法参考

目前快代理的高匿名代理可以使用了,

目标测试网址是百度

微博爬取

这貌似是静态页面,这个有视频的小栏的在class这个类里面

image-20210204110233369

image-20210204111033384

这个点击之后才出现下拉框

image-20210204111218761

这个链接地址就是视频所在url。

完善

useragent应该使用动态的

image-20210204113550428

点击之后这就是链接地址。

但是真正位置还需要加上一个前缀image-20210204113705545

其实也就是源码中的点击之后获得源码中获得的url。他request的源代码到这一层就结束了。

image-20210204163556591

image-20210204184830538

我们要请求的地址:https://f.video.weibocdn.com/Q9fBi7UMlx07K3B0OMWI010412013yjx0E010.mp4?label=mp4_hd&template=480x720.25.0&trans_finger=d8257cc71422c9ad30fe69ce9523c87b&ori=0&ps=1EO8O2oFB1ePdo&Expires=1612438106&ssig=s8dF79pY%2FR&KID=unistore,video

脚本中的编码

https%3A%2F%2Ff.video.weibocdn.com%2FQ9fBi7UMlx07K3B0OMWI010412013yjx0E010.mp4%3Flabel%3Dmp4_hd%26template%3D480x720.25.0%26trans_finger%3Dd8257cc71422c9ad30fe69ce9523c87b%26ori%3D0%26ps%3D1EO8O2oFB1ePdo%26Expires%3D1612438106%26ssig%3Ds8dF79pY%252FR%26KID%3Dunistore%2Cvideo

数据保存在这里面但是经过编码的。

%2F是/

%3A是:

%3F是?

%3D是=

%26是&

%25是%

%2C是, (逗号)

.(点)还是不变

下划线没有变

URL编码参考

所以这就涉及对Url进行解码:

编码解码代码实现

所以我们接下来需要进行的是如何获得script里面对应的编码好的url。

参考b站那个代码

image-20210204193250054

image-20210204214853369

都是上面红框那一栏。

如何解析出来说一个json数据格式(他妈的)

第一次解析之后,json数据格式一看

image-20210205093318276

最终得到里面的html,自己加上html封装一下,得到

image-20210205094849433

image-20210205095941673

这里前面的想法

html_data.text是前面requst.get返回的数据
# 下面的思路
找到对应的script下的标签有不同script但是发现视频那一栏的html在索引为2的那个script里面然后去掉前后一些东西得到一个json字符串使用Loads解析json最终得到里面的hml字符串html_data =html_data.text

# 正则表达式匹配
video_title= re.findall('<script charset="utf-8">FM.view\(([\d\D]*?)\)</script>',html_data)  # 返回得是一个列表
if(len(video_title)>=3):
    video_title = video_title[2]
    with open('第一次得到正则.html','w',encoding='utf-8') as f:
        # if(len(video_title)!=0):
        f.write(video_title)

    # 得到的是一个json格式的字符串
    json_scipt_data = json.loads(video_title)
    json_html_str= json_scipt_data['html']
    #  得到是html字符串
    # video\.weibocdn([\d\D]*?)unistore
    # https://f.video.weibocdn.com 参数  =unistore,video
    #  所以我们需要拼接一下然后转码,因为得到的字符串参数是没有编码的
else:
    print('没有匹配成功')

基于上面,经过测试发现,我直接全局正则匹配对应的视频URL链接。还稳定

推荐正则表达式测试使用得软件:没有广告:RegexMatchTracerCr

下载位置

re.findall('video\.weibocdn([\d\D]*?)unistore',contents)

结果又发现取得真正得url。

他前缀不一定一样,脑壳痛

image-20210205105352787

那我们就先搞微博开头得,你正常解码一对比,发现

image-20210205110028455

你解析得直接点击原来发现服务器给你禁止了。

python爬虫禁止访问解决办法

换个ip,有效

image-20210205110507360

提取标题

image-20210205140131771

对于H3标签下,a和img数量不固定,但是还

开头,里面有个谁的微博视频那个标签目前发现是固定的。

正则表达式:

python去掉标签及标签里面的内容

已经这个来划分。

list_title_s(.*?)的微博视频

image-20210205141145035

然后我再删除非汉字(文本的内容)

版本1.1总结

一定要带着cookie走,如何usergent换他里面的,不然会返回东西,但不是你想要的。

这里写完了:

image-20210205151555989

该py文件可以直接运行,只需要下载依赖库

因为我自己安装的是anaconda+python3.7再加上里面安装的库

image-20210205152216818

image-20210205152302689

没有使用selemium这种操作,里面的文件只是当时的一个思路,但实际中未使用。

这是最原始的版本,能爬取视频

但是需要优化的是:

1:动态从csv中获取相同IP,即使用代理池,ip全部保存在Ip_pool.csv中  
2:当过多访问ip导致被封时候,再动态获取ip
3:注意获得的视频地址和标题数目是否一样多
4:视频地址解析目前其实有问题,因为不一定都是https://f.video.weibocdn 开头的
4:保存该视频链接来源,这样打开数据就知道该视频哪里来的(这个暂时不需要,都写微博搞笑视频就行了)
5:对一些错误进行处理
6:进行实现多页面翻页
6:正则表达式需要优化
7:多线程
8:动态使用user-agent
9: 架构一点,多封装

对于Ip的csv文件的处理

# 第一点优化实现,顺序使用,如果该ip被屏蔽之后就依次调用第二个,这样就不会因为随机数重复使用csv中被屏蔽的ip
import pandas as pd 
#  这里使用读取csv来获得ip,不用以下方式就注释掉,直接用上面的就可以
df = pd.read_csv("ip_pool.csv")
# #  这里直接变成数组格式
df_list=df.values.tolist()
# 我没有必要取随机数,如果这一个不行我直接取下一个
# 这个索引是从0开始
csv_ip_local = 0   # csv中用到第几个Ip了
proxies = {
            # type :ip   行列定位
            df_list[csv_ip_local][0]: df_list[csv_ip_local][1]
        }
// 但这样会存在一个问题,因为从快代理的ip我以前使用过被微博禁了
思路:获取Ip的时候测试是否有效不仅经过`http://httpbin.org/get`,还经过微博网站试探一下,如果可以就加入csv里面。

出现这个问题

image-20210207084936318

连续几个之后就不能用了。

我觉得是因为

image-20210207094030297

对于WeiBo1.3.py是对正则表达式的完全重构。针对

image-20210207084936318

这里出现不可用的情况是因为有些视频也是别人搬运的,在别的网站上

WeiBo1.3.py之前的都是只获得https://f.video.weibocdn.com :这种开头类型的,但是对于从秒拍视频这种搬运的https://n1cdn.miaopai.com/stream/就无法获取,至于为什么获取的视频和得到的标题能一一对于,是因为你获得标题的正则表达式:image-20210207100040793

后缀是:的微博视频 因为搬运的后缀:比如从秒拍视频的来的:image-20210207100134865

所以前面把外面视频网址去掉,视频标题把外面视频标题去掉,所以正好一一对应。

解决办法

把视频的栏目这一栏放到一个整体来读取

image-20210207100523480

你会发现UG_list_v2 clearfix是每个视频的标题的class。

所以得到的视频的标题:UG_list_v2 clearfix([\d\D]*?)视频。然后再去解析。

遇见问题:

image-20210207113623332

上面这是ip被封了。

版本1.5添加:

优化:
	1:ip和useragent都取随机数,如果一个ip重复读取更容易被封
	2:被封的ip需不需要再删掉,全部ip被封在调用爬取匿名代理的函数(这个idea方法暂定)

1:useragent都取随机数

参考

​ weibo1.4.py经常ip被封只能读取下一个

实现:

​ 使用fake-useragent

 pip install fake-useragent

image-20210301100243614

2:ip取随机数

# 重新获得随机IP    
def get_randon_ip():
    if(list_ip_len):
        csv_ip_local = random.randint(0,list_ip_len-1) # csv中用到第几个Ip了
    else:
        csv_ip_local=0
        print('已经没有可用的IP地址了')  # 后面可以在这里选择是否重新爬取IP形成代理池
    new_proxies = {
        # type :ip   行列定位
        df_list[csv_ip_local][0]: df_list[csv_ip_local][1]
    }
    return new_proxies

使用selenium

目标:人人网登录

image-20210204133053337

这样子就会直接跳转。

获取cookies(本来就已经存在cookie),这时候对于如何页面跳转能够一直保持登录状态。

记录登录状态。

image-20210204133435219

这种效率不高

因为一个新的界面就会当前js,css样式表等.

这种效率比request低很多.

定位元素使用chropath插件.

对人人网测试使用父组件的div也可以.click函数

遇见的一些错误

https://stackoverflow.com/questions/65755603/selenium-ssl-client-socket-impl-cc-handshake-failed