刚开始学爬虫,分享一下自己爬取成功的经历,本章将详细说明自己整个爬取流程
步骤一:准备工作
1.导入需要的库
import requests
from lxml import etree
import re
# 创建Session对象,可以在多次请求之间保持cookies
session=requests.Session()
2.获取主网页链接传入url中,并设置请求头模拟浏览器的请求
# 某视频主网页
url='https://www.某视频地址.com/'
# 请求头
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'}
3.发送get请求获取主网页HTML文本传入page_text中,并用lxml中的etree.HTML将其转换为xpath可以解析的内容传入html中
# 获取主网页文本内容并用etree.HTML将其转换为xpath可以访问的内容
page_text=requests.get(url,headers=headers).text
html=etree.HTML(page_text)
步骤二:解析主网页获取信息
1.打开开发者模式在元素中定位视频位置
经观察红框中的就是视频的真实地址
2.调出网页源代码观察可以直接看到首个视频的地址,但是其他视频的地址并没有显示,可以判断出首视频地址是XHR动态显示出来的,其他视频并没有在主页自动播放,如果从主页抓取只能抓到首个视频的地址,因此得进入每个视频的子网页中去抓取
3.点击主网页视频进入视频子网页观察网址,可以发现视频子网页地址就是“主网页地址+video_1792432"
这不就是网页源代码中a的href中的内容嘛,所以只要获取主网页视频对应a的href内容再加上主网页地址不就是所有视频子网页的地址了嘛
4.利用html.xpath获取所有视频对应a中href中的内容并传入video_adress中
经过观察发现主网页中首5个视频与人物、万象中的视频在网页源码中的div命名是不同的,所以用or来获取所有的视频内容
# 利用xpath访问获取主网页中所有视频的子网页地址(以数组形式储存在video_address中)
video_address=html.xpath('//div[@class="vervideo-tbd" or @class="vervideo-bd"]/a/@href')
# 利用xpath访问获取主网页中所有视频的名字(以数组形式储存在video_name中)
video_name=html.xpath('//div[@class="vervideo-name" or @class="vervideo-title"]/text()')
print(video_address)
print(video_name)
打印输出可得到所有视频编号以及视频标题
步骤三:解析单个视频子网页获取信息
1.编写循环构建所有视频子网页地址并传入url2中
# 通过for循环获取单个视频的子网页地址
for i in video_address:
# 真正的视频子网页为 主网页+视频的子网页
url2='https://www.某视频地址.com/'+i
print(url2)
2.一般视频都是js动态加载出来的,你可能在视频子网页用开发者模式可以看到视频的地址,但是如果你查看视频子网页的源代码你会发现根本找不到,所以如果还用xpath解析网页是解析不到的,因为获取到的子网页源代码中根本就没有视频地址
3.在视频子网页通过XHR抓取视频信息(抓取不到的可以播放视频或者刷新网页播放)
4.观察其标头可以发现它的请求网址、Content-Type、Accept以及它的响应并分析
通过观察Content-Type和Accept可以看出服务器响应的是json类型的数据,将响应的内容用json工具解析一下
可以得到一个假地址,将其与真地址比较
# 假地址:https://video.某视频地址.com/mp4/short/20240305/1709808096840-16021085-hd.mp4
# 真地址:https://video.某视频地址.com/mp4/short/20240305/cont-1792432-16021085-hd.mp4
观察得出只要将假地址中的”1709808096840“替换成”cont-1792432“就能得到视频的真地址;而其中"1792432"正是视频的编号
通过分析可以得出:访问请求地址——>得到响应的json数据——>解析数据得到假地址——>替换假地址——>得到真地址
5.分析请求地址
观察可得地址contld=的部分就是视频的编号,而mrd部分就是个随机数(可以用随机数生成也可以直接用并不影响)
# 通过for循环获取单个视频的子网页地址
for i in video_address:
# 真正的视频子网页为 主网页+视频的子网页
url2='https://www.某视频地址.com/'+i
# 其中i=video_视频编号;获取视频编号储存到id中
id=i[6:]
#通过在视频子网页抓包XHR获取视频的请求地址为(https:...+视频编号+mrd);mrd为随机数不改变也不影响
url3='https://www.某视频地址.com/videoStatus.jsp?contId='+ id +'&mrd=0.9030122729291468'
步骤四:获取视频真正地址
1.如果我们直接访问视频的请求地址会无法访问
要在请求头中加入视频子网页地址表示你是从视频子网页进来的,并且用session对请求地址发起访问
# 如果直接访问视频的请求地址会显示错误,所以要给请求头加上Referer表示你是从视频子网页进来的
headers2 = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
'Referer': url2
}
# 通过json()获取视频的json格式的数据并储存到video_response中
video_response=session.get(url3,headers=headers2).json()
2.获取响应中的假地址并传入到f_video_url中
# 视频地址在srcUrl中,通过[][][]三层获取视频地址;但是这是一个假的地址
f_video_url=video_response['videoInfo']['videos']['srcUrl']
3.利用正则对假地址进行替换得到真地址并传入到t_video_url中
# https://video.某视频地址.com/mp4/adshort/20190326/1709716685542-13736020_adpkg-ad_hd.mp4(伪装的地址)
# https://video.某视频地址.com/mp4/adshort/20190326/cont-1534885-13736020_adpkg-ad_hd.mp4(真正的地址)
# 观察可知只要将伪装的地址中的1709716685542这部分替换成cont-视频编号即可
a="cont-"+id
# 使用正则定位1709716685542
positioning=r'(?<=\/)\d+(?=-)'
# 使用re.sub()定位假地址中1709716685542的位置并用"cont-"+id进行替换得到真正的视频地址
t_video_url=re.sub(positioning,a,f_video_url)
4.打印输出全部视频地址和视频标题
j=0
# 通过for循环获取单个视频的子网页地址
for i in video_address:
# 真正的视频子网页为 主网页+视频的子网页
url2='https://www.某视频地址.com/'+i
# 其中i=video_视频编号;获取视频编号储存到id中
id=i[6:]
#通过在视频子网页抓包XHR获取视频的请求地址为(https:...+视频编号+mrd);mrd为随机数不改变也不影响
url3='https://www.某视频地址.com/videoStatus.jsp?contId='+ id +'&mrd=0.9030122729291468'
# 如果直接访问视频的请求地址会显示错误,所以要给请求头加上Referer表示你是从视频子网页进来的
headers2 = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
'Referer': url2
}
# 通过json()获取视频的json格式的数据并储存到video_response中
video_response=session.get(url3,headers=headers2).json()
# 视频地址在srcUrl中,通过[][][]三层获取视频地址;但是这是一个假的地址
f_video_url=video_response['videoInfo']['videos']['srcUrl']
# https://video.某视频地址.com/mp4/adshort/20190326/1709716685542-13736020_adpkg-ad_hd.mp4(伪装的地址)
# https://video.某视频地址.com/mp4/adshort/20190326/cont-1534885-13736020_adpkg-ad_hd.mp4(真正的地址)
# 观察可知只要将伪装的地址中的1709716685542这部分替换成cont-视频编号即可
a="cont-"+id
# 使用正则定位1709716685542
positioning=r'(?<=\/)\d+(?=-)'
# 使用re.sub()定位假地址中1709716685542的位置并用"cont-"+id进行替换得到真正的视频地址
t_video_url=re.sub(positioning,a,f_video_url)
# 输出真正的视频地址和视频名字
print(t_video_url,video_name[j])
j=j+1
print("爬取的视频个数为:",j)
附完整代码:
import requests
from lxml import etree
import re
# 创建Session对象,可以在多次请求之间保持cookies
session=requests.Session()
# 某视频主网页
url='https://www.某视频地址.com/'
# 请求头
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'}
# 获取主网页文本内容并用etree.HTML将其转换为xpath可以访问的内容
page_text=requests.get(url,headers=headers).text
html=etree.HTML(page_text)
# 利用xpath访问获取主网页中所有视频的子网页地址(以数组形式储存在video_address中)
video_address=html.xpath('//div[@class="vervideo-tbd" or @class="vervideo-bd"]/a/@href')
# 利用xpath访问获取主网页中所以视频的名字(以数组形式储存在video_name中)
video_name=html.xpath('//div[@class="vervideo-name" or @class="vervideo-title"]/text()')
j=0
# 通过for循环获取单个视频的子网页地址
for i in video_address:
# 真正的视频子网页为 主网页+视频的子网页
url2='https://www.某视频地址.com/'+i
# 其中i=video_视频编号;获取视频编号储存到id中
id=i[6:]
#通过在视频子网页抓包XHR获取视频的请求地址为(https:...+视频编号+mrd);mrd为随机数不改变也不影响
url3='https://www.某视频地址.com/videoStatus.jsp?contId='+ id +'&mrd=0.9030122729291468'
# 如果直接访问视频的请求地址会显示错误,所以要给请求头加上Referer表示你是从视频子网页进来的
headers2 = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
'Referer': url2
}
# 通过json()获取视频的json格式的数据并储存到video_response中
video_response=session.get(url3,headers=headers2).json()
# 视频地址在srcUrl中,通过[][][]三层获取视频地址;但是这是一个假的地址
f_video_url=video_response['videoInfo']['videos']['srcUrl']
# https://video.某视频地址.com/mp4/adshort/20190326/1709716685542-13736020_adpkg-ad_hd.mp4(伪装的地址)
# https://video.某视频地址.com/mp4/adshort/20190326/cont-1534885-13736020_adpkg-ad_hd.mp4(真正的地址)
# 观察可知只要将伪装的地址中的1709716685542这部分替换成cont-视频编号即可
a="cont-"+id
# 使用正则定位1709716685542
positioning=r'(?<=\/)\d+(?=-)'
# 使用re.sub()定位假地址中1709716685542的位置并用"cont-"+id进行替换得到真正的视频地址
t_video_url=re.sub(positioning,a,f_video_url)
# 输出真正的视频地址和视频名字
print(t_video_url,video_name[j])
j=j+1
print("爬取的视频个数为:",j)