抓取网页视频(学视频剪辑爬虫获取视频素材信息的方法和方法)
优采云 发布时间: 2022-03-04 00:04抓取网页视频(学视频剪辑爬虫获取视频素材信息的方法和方法)
最近在学习视频剪辑,从网上找了很多视频素材,也找到了一些不错的素材网站,比如这个网站:有很多免费的high-定义视频材料。有时候想获取某个关键词搜索到的所有相关视频素材的信息,但是手动点击效率太低。最近正好在学习python爬虫,所以想到了用爬虫来获取视频素材信息。
比如我要搜索无人机相关的视频,我在搜索框输入drone,出来的网址是这样的。
我们打开chrome的开发者工具,刷新网页,可以看到第一个请求的响应,里面收录了很多视频素材信息。
拉下页面,看到刷新了新的视频素材,提醒我们页面是通过ajax异步更新的,我们选择XHR查看ajax请求。
首先,我们分析了第一个。如果没有我们网页上的视频信息,它应该是一个外部链接信息。我们不能使用它。我们直接看后续的请求。后面的每一个请求格式看起来都一样,我们来分析第一个。
我们可以看到这是一个 GET 类型的请求,有两个参数:path 和 params。params 的值是一个字典,其中收录许多其他参数。当我们对比其他请求的参数时,可以发现path参数的内容完全一样,只是params参数中更新了pge和offset_resp_videos。并且pge值从1更新到4后不会改变,offset_resp_videos更新到106后也不会改变。
我们进一步分析了反应。当 pge 为 1 和 2 时,每个响应收录 30 条视频信息。pge为3时,只有9条视频信息。当 pge 为 4 时,没有视频信息。这意味着当 pge=3 时,所有视频信息都已获取。所以当我们模拟ajax获取视频信息的时候,pge的范围是1-3,通过分析还可以得到:offset_resp_videos=(pge-1) * 30 + 37,这时候我们可以构造通过python模拟ajax请求的url。
我们通过查看Elements信息可以看到每个视频的html信息。
其中,前30个视频通过静态请求获取,其余通过ajax异步请求获取。静态获取是html格式的,我们可以直接解析;通过ajax获取的response是json格式的,我们需要使用json库处理得到视频信息的html文本。
可以看到,在ajax响应中,elements元素是一个列表,其中的每个元素都是视频信息的html文本,和静态网页中的格式是一样的,所以我们需要使用json 库来获取 ajax 响应中的视频信息元素。
对于视频素材,我们更关心id、时长、分辨率、标题、预览图片链接、视频链接。我们可以通过xpath获取相关信息。
以下是相关代码:
from urllib.parse import urlencode
import requests
import json
from lxml import etree
import time
import csv
items = []
headers = {
'Host': 'mazwai.com',
'Referer': 'https://mazwai.com/stock-video-footage/drone',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
}
# 获取静态网页
def get_first_page():
base_url = "https://mazwai.com/stock-video-footage/drone"
try:
rsp = requests.get(base_url, headers=headers)
if rsp.status_code == 200:
return rsp.text
except requests.ConnectionError as e:
print('Error:', e.args)
# 解析静态网页
def parse_html_result(result):
html = etree.HTML(result)
elements = html.xpath('//div[contains(@class, "video-responsive")]')
print(len(elements))
for element in elements:
element = etree.HTML(etree.tostring(element))
parse_html_element(element)
# 模拟ajax请求获取动态网页
def get_follow_page(page, start_idx):
base_url = "https://mazwai.com/api/?"
params = '{' + '"pge":{},"recordsPerPage":30,"recordsPerPage":30,"rec":30,"json_return":true,"infinite_scroll": true,"offset_resp_videos":{},"category": "drone"'.format(page, start_idx + (page-1)*30) + '}'
total = {
'path': 'elasticsearch/listResults',
'params': params
}
url = base_url + urlencode(total)
print(url)
try:
rsp = requests.get(url, headers=headers)
if rsp.status_code == 200:
return rsp.text
except requests.ConnectionError as e:
print('Error:', e.args)
# 解析ajax响应
def parse_json_result(result):
rsp = json.loads(result)
for element in rsp['elements']:
element = etree.HTML(element)
parse_html_element(element)
# 解析包含视频信息的单个元素
def parse_html_element(element):
item = []
id = element.xpath('//div[contains(@class, "video-responsive")]/@id')
imgsrc = element.xpath('//img/@src')
videosrc = element.xpath('//img/@data-video-source')
title = element.xpath('//img/@title')
duration = element.xpath('//div[@class="video-resolution-length-info"]/span[@class="duration"]/text()')
resolution = element.xpath('//div[@class="video-resolution-length-info"]/span[@class="resolution"]/text()')
item.append(id[0])
item.append(title[0])
item.append(duration[0])
item.append(resolution[0])
item.append(imgsrc[0])
item.append(videosrc[0])
items.append(item)
def write_csv():
with open('data.csv', 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['id', 'title', 'duration', 'resolution', 'img_url', 'video_url'])
writer.writerows(items)
# 主函数
def main():
# 获取第一页并解析
result = get_first_page()
if result is not None:
parse_html_result(result)
time.sleep(2)
# 获取后续页并解析
for page in range(1, 4):
result = get_follow_page(page, 37)
parse_json_result(result)
time.sleep(2)
# 存成csv文件
write_csv()
if __name__ == '__main__':
main()
结果:
最后将提取的信息保存为csv文件,后续的图片和视频文件可以通过链接自动下载保存。
我们可以通过修改程序来爬取其他搜索信息,支持输入关键字信息,通过总条目数自动计算需要爬取多少页,这里不再赘述。