Python爬虫实战案例——第二例

某某美剧剧集下载(从搜索片名开始)
本篇文章主要是为大家提供某些电影网站的较常规的下载电影的分析思路与代码思路(通过爬虫下载电影),我们会从搜索某部影片的关键字开始直到成功下载某一部电影。

地址:aHR0cHM6Ly93d3cuOTltZWlqdXR0LmNvbS9pbmRleC5odG1s

先来分析页面

在这里插入图片描述

打开开发者工具,然后再搜索框输入任意内容开始搜索影片(如搜索战火)并抓包

在这里插入图片描述

从XHR来看的话返回的都是js文件,所以我们可以先考虑document中的html文档是否包含了我们需要的有效数据。

在这里插入图片描述

document中只返回了一个包,并且通过预览来看的话我们可以看到通过关键字搜索出来的电影是存在于这个html中的,所以我们就可以直接通过xpath解析将这些电影的片名解析出来,便于后面我们对影片进行选择。然后就可以进入到电影的详情页面(xpath解析出详情页的url)了。例如此处我们选择《兄弟连》这部电影。

在这里插入图片描述

进入到详情页之后,我们需要判断这部影片是否已经更新完成,因为下面我们需要选择播放线路,不同的播放线路已更新的剧集可能不同,但是经过对多部影片的详情页分析(此处不再贴图,大家自己去观察)发现,已完结的影片是不会存在上述问题的。但是正在连载中的影片可能就存在这样的问题,所以我们需要判断一下已经连载的剧集与这些播放线路中的剧集集数是否相等,如果相等的话才是可用的线路,否则是不可用的线路。当然也有可能存在一条线路都无法播放的情况,这个就是服务器的问题了,咱们客户端这边是没办法处理的。之后我们就要根据选择的线路去到播放页面就可以准备下载电视剧了。

此处我们选择的是九九云线路,来到播放页面之后通过抓包我们会发现并没有媒体文件,但是存在着m3u8与ts的包,因此我们能够判断出这个站点的视频是被分割成很多分的片段了。

在这里插入图片描述

接下来就是要想办法把这些ts视频下载下来了,通常情况下,这些文件的url会存在于一个m3u8的文件之中,所以我们需要先将m3u8下载下来。从播放页面的源码中我们可以解析出m3u8文件的下载地址(为了方便此处我就不再去请求源码了,直接从elements中看,大家平时的时候一定是养成习惯把源码下载到本地进行分析)

在这里插入图片描述

然后将next后面的url解析出来再进行请求,就会看到里面存在着一个新的m3u8文件的地址。

在这里插入图片描述

接下来就是通过正则将这个文件中存在的这个地址提取出来进行拼接再进行请求就能够获取到所有的ts文件所在的地址了。

在这里插入图片描述

下一步就是将这些ts文件的地址提取出来,同样我们选择正则进行提取(或者使用专门处理m3u8的第三方包进行提取),提取出来后拼接成正常的链接,存放到一个列表中,然后再遍历列表依次请求这些url并按照顺序将视频进行保存。

在这里插入图片描述

保存之后通过ffmpeg对视频进行合成,关于ffmpeg的配置请大家自行查阅一下相关资料。

在这里插入图片描述

合成后的视频

在这里插入图片描述

由于时间关系,只下载了200个片段进行合成,有兴趣的朋友可以改写成并发请求的方式下载所有的片段进行合成。完整代码如下:

import os.path
import re
import requests
import urllib3
from lxml import etreeclass SendRequest:"""基本请求模板,待完善"""urllib3.disable_warnings()def __init__(self):self.ABS_PATH = os.path.abspath(os.path.dirname(__file__))self.url = ''self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'}self.cookies = {}  # cookie设置self.data = {}  # 表单数据self.page = 1  # 翻页控制参数self.session = requests.session()# self.movie = '测试'# print(f'{self.ABS_PATH}/{self.movie}(临时文件)/{self.movie}.m3u8')# print(f'{self.ABS_PATH}/{self.movie}/{self.movie}.mp4')@propertydef UGetRequest(self):response = self.session.get(url=self.url, headers=self.headers, cookies=self.cookies, verify=False)return response@UGetRequest.setterdef UGetRequest(self, kwargs: dict):if kwargs.get('url'):self.url = kwargs.get('url')if kwargs.get('referer'):self.headers['referer'] = kwargs.get('referer')@propertydef UPostRequest(self):response = self.session.post(url=self.url, headers=self.headers, cookies=self.cookies, data=self.data,verify=False)return response@UPostRequest.setterdef UPostRequest(self, kwargs: dict):if kwargs.get('url'):self.url = kwargs.get('url')if kwargs.get('referer'):self.headers['referer'] = kwargs.get('referer')class MeiJu99(SendRequest):def __init__(self):super().__init__()def synthesis(self):"""合成视频"""if not os.path.exists(self.movie):os.mkdir(self.movie)cmd = f'ffmpeg.exe -f concat -safe 0 -i {self.ABS_PATH}\\{self.movie}(临时文件)\\{self.movie}.m3u8 -c copy {self.ABS_PATH}\\{self.movie}\\{self.movie}.mp4'os.system(cmd)def download_mvs(self, total_mv_urls):"""下载所有片段"""if not os.path.exists(self.movie+'(临时文件)'):os.mkdir(self.movie+'(临时文件)')num = 1# 按照ffmpeg的格式将ts文件的路径写入到一个m3u8文件之中用于合成视频new_m3u8_file = open(self.movie+'(临时文件)'+'/'+self.movie+'.m3u8', 'a', encoding='utf-8')for url in total_mv_urls:self.UGetRequest = {'url': url}res = self.UGetRequestwith open(self.movie+'(临时文件)'+'/'+str(num)+'.ts', 'wb')as f:f.write(res.content)new_m3u8_file.write("file '%s\%s\%d.ts'" % (self.ABS_PATH, self.movie+'(临时文件)', num))new_m3u8_file.write('\n')print(str(num) + '下载成功')num+=1if num == 201:breaknew_m3u8_file.close()self.synthesis()def play_page(self, play_pages_url):"""播放页面提取下载链接"""self.UGetRequest = {'url': play_pages_url}response = self.UGetRequesttext_html = response.content.decode()with open('playpage.html', 'w', encoding='utf-8')as f:f.write(text_html)m3u8_url = re.findall('var next="(.*?)";var prePage=', text_html)[0]    # 提取播放页面中的m3u8文件的地址self.UGetRequest = {'url': m3u8_url}m3u8_file = self.UGetRequest.contentwith open('1.m3u8', 'wb')as f:f.write(m3u8_file)# 请求上方获取到的m3u8_url以获取存放了ts地址的m3u8last_m3u8_url = m3u8_url.split('/2')[0] + re.search('/\d+/\w+/[\d+kb/]*\w+/index\.m3u8', m3u8_file.decode()).group()self.UGetRequest = {'url': last_m3u8_url}response = self.UGetRequest.content.decode()# 解析并保存所有的ts地址total_mv_urls = [m3u8_url.split('/2')[0]+i for i in re.findall('/\d+/\w+/\d+\w+/hls/\w+\.ts', response)]self.download_mvs(total_mv_urls)def index(self, index_url):"""电影详情页面"""self.UGetRequest = {'url': index_url}response = self.UGetRequesttext_html = response.content.decode()with open('index.html', 'w', encoding='utf-8')as f:f.write(text_html)tree = etree.HTML(text_html)using_lines = tree.xpath('//*[@id="playTab"]/div[1]/ul//li//text()')    # 可使用线路(名称)play_tab = tree.xpath('//*[@id="playTab"]/div')     # 下载线路mv_information = ''.join(tree.xpath('//*[@id="zanpian-score"]/ul//text()'))     # 电影信息status = ''.join(tree.xpath('//*[@id="zanpian-score"]/ul/li[2]//text()'))if '完结' not in status:numbers_sets = ''.join(re.findall('集数:共(.*?)集 每集\d+分钟|状态:更新至(.*?)集', mv_information)[0])for i, tab in zip(range(len(using_lines)), play_tab[1:]):tab_num = len(tab.xpath('./ul/li'))if tab_num == int(numbers_sets):print('%d.' % (i+1), using_lines[i]+'(可用)', end='\t')else:print('%d.' % (i+1), using_lines[i]+'(不可用)', end='\t')else:for i, tab in zip(range(len(using_lines)), play_tab[1:]):print('%d.' % (i + 1), using_lines[i], end='\t')print()download_num = int(input('请选择下载线路(输入编号):'))play_pages_urls = ['https://www.99meijutt.com'+i for i in play_tab[download_num].xpath('./ul//li/a/@href')]for play_pages_url in play_pages_urls:self.play_page(play_pages_url)breakdef search(self):"""搜索页面采集"""titles = []self.UPostRequest = {'url': 'https://www.99meijutt.com/search.php'}self.data['searchword'] = input('请输入影片关键字或主演名:')response = self.UPostRequesttext_html = response.content.decode()with open('search.html', 'w', encoding='utf-8') as f:f.write(text_html)tree = etree.HTML(text_html)div_lst = tree.xpath('//*[@id="content"]/div')print('搜索到的电影如下:')for i, div in zip(range(1, len(div_lst)), div_lst):  # 遍历数组与div列表为标题设置编号title = div.xpath('./div[1]/a/@title')[0]if i % 2 != 0 and i != len(div_lst)-1:print(str(i) + '.' + title, end='\t\t')else:print(str(i) + '.' + title)titles.append(title)num = int(input('请输入您要下载的电影序号:'))self.movie = titles[num-1]index_url = 'https://www.99meijutt.com' + div_lst[num-1].xpath('./div[1]/a/@href')[0]self.index(index_url)if __name__ == '__main__':mj = MeiJu99()mj.search()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/102414.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单理解Socket

TCP/IP 要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何再它们之间传输的标准, 从字面意思来看T…

《剑指Offer》模块三 思维题【面试官可能考的13道思维算法题】

思维题 1. 扑克牌的顺子【思维题】 原题链接 1. 判断所有牌中 是否出现 重复 2. 有序sort后 判断是否最大差距 <4 class Solution { public:bool isContinuous( vector<int> nums) {sort(nums.begin(), nums.end());for (int i 1; i < nums.size(); i )if …

js使用for of遍历map

//使用for of遍历map console.log("---") console.log(odata.studentDetails) let obj odata.studentDetails[0].answerSituation for(let [key,value] of Object.entries(obj)){console.log(value) }

【业务功能篇73】web系统架构演变-单体-集群-垂直化-服务化-微服务化

1.服务架构的演 1.1 单体架构 单体架构应该是我们最先接触到的架构实现了&#xff0c;在单体架构中使用经典的三层模型&#xff0c;即表现层&#xff0c;业务逻辑层和数据访问层。 单体架构只适合在应用初期&#xff0c;且访问量比较下的情况下使用&#xff0c;优点是性价比很…

淘宝商品优惠券详情item_get_app-获得淘宝app商品详情原数据

item_get_app-获得淘宝app商品详情原数据 taobao.item_get_app 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;调用API接口入口secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09…

Redis系列(三):深入解读Redis主从同步机制

首发博客地址 https://blog.zysicyj.top/ Redis高可靠靠什么保证&#xff1f; 为什么要提这个呢&#xff0c;因为Redis主从库目的呢其实就是为了实现高可靠。上篇文章中我们说过Redis的AOF、RDB日志其实就是为了减少数据丢失&#xff0c;这是高可靠的一部分。 这篇文章呢&#…

C++ STL常用算法(详解)

C常用算法 C sort()排序函数用法详解 C STL 标准库提供有很多实用的排序函数&#xff0c;如表 1 所示。通过调用它们&#xff0c;我们可以很轻松地实现对普通数组或者容器中指定范围内的元素进行排序。 ​ 表 1 C STL 排序函数 函数名用法sort (first, last)对容器或普通数…

C语言学习系列-->【关于qsort函数的详解以及它的模拟实现】

文章目录 一、概述二、qsort函数参数介绍三、qsort实现排序3.1 qsort实现整型数组排序3.2 qsort实现结构体数组排序 四、模拟实现qsort函数 一、概述 对数组的元素进行排序 对数组中由 指向的元素进行排序&#xff0c;每个元素字节长&#xff0c;使用该函数确定顺序。 此函数使…

MES生产报工管理

一、MES生产报工管理的定义与功能&#xff1a; MES生产报工管理是指利用制造执行系统&#xff08;MES&#xff09;对生产过程进行实时监控、数据采集和分析&#xff0c;并及时记录和报告生产工单的实际完成情况。其主要功能包括&#xff1a; 1. 实时数据采集&#xff1a;通过…

【爬虫练习之glidedsky】爬虫-基础2

题目 链接 爬虫往往不能在一个页面里面获取全部想要的数据&#xff0c;需要访问大量的网页才能够完成任务。 这里有一个网站&#xff0c;还是求所有数字的和&#xff0c;只是这次分了1000页。 思路 找到调用接口 可以看到后面有个参数page来控制页码 代码实现 import reques…

通过python在unity里调用C#接口

log: 背景 最近在做虚拟人底层驱动sdk测试&#xff0c;因为后端使用的是C#,我个人更倾向于python编程辅助测试工作&#xff0c;测试sdk需要通过开发提供的接口方法文档&#xff0c;通过传测试场景参数调用方法进行单元测试 技术&工具 项目语言 C# 项目工具 unity 测试…

packge.json中的browserlistrc配置有什么用?

theme: smartblue 前端开发中&#xff0c;需要考虑前端开发中&#xff0c;需要考虑CSS及JS的兼容性&#xff0c;browserlistrc指定了需要兼容的浏览器。 数据来源 Browserslist 的数据都是来自caniuse.com的。 使用方法 package.json {"browserslist": ["l…

大语言模型之四-LlaMA-2从模型到应用

最近开源大语言模型LlaMA-2火出圈&#xff0c;从huggingface的Open LLM Leaderboard开源大语言模型排行榜可以看到LlaMA-2还是非常有潜力的开源商用大语言模型之一&#xff0c;相比InstructGPT&#xff0c;LlaMA-2在数据质量、培训技术、能力评估、安全评估和责任发布方面进行了…

YOLOv5+deepsort实现目标追踪。(附有各种错误解决办法)

一、YOLOv5算法相关配置 🐸这里如果是自己只想跑一跑YOLOV5的话,可以参考本章节。只想跑通YOLOv5+deepsort的看官移步到下一章节。 1.1 yolov5下载 🐸yolov5源码在github下载地址上或者Gitee上面都有。需要注意的是由于yolov5的代码库作者一直在维护,所以下载的时候需…

【python】python开源代理ip池

一、前言 随着互联网的不断发展&#xff0c;越来越多的应用需要使用高匿代理IP才能访问目标网站&#xff0c;而代理IP作为一种能够隐藏本机真实IP地址的工具&#xff0c;在网络抓取、搜索引擎排名、广告投放、反爬虫等方面有着广泛的应用场景。但是&#xff0c;由于代理IP的稳…

open suse 15.5(任意版本) 使用阿里云的repo

一、shell suse 的包管理工具叫 zypper. zypper addrepo -f http://mirrors.aliyun.com/opensuse/distribution/leap/15.5/repo/oss/ openSUSE-15.5-Oss zypper addrepo -f http://mirrors.aliyun.com/opensuse/distribution/leap/15.5/repo/non-oss/ openSUSE-15.5-Non-Oss …

【Python】代理池针对ip拦截破解

代理池是一种常见的反反爬虫技术&#xff0c;通过维护一组可用的代理服务器&#xff0c;来在被反爬虫限制的情况下&#xff0c;实现数据的爬取。但是&#xff0c;代理池本身也面临着被目标网站针对ip进行拦截的风险。 本文将详细介绍代理池针对ip拦截破解的方法&#xff0c;包含…

psycopg2 使用ThreadedConnectionPool 工具封装

psycopg2 介绍 psycopg2库介绍: Psycopg2是一个用于Python编程语言的第三方库&#xff0c;用于访问PostgreSQL数据库系统。它提供了一组工具和方法&#xff0c;可以轻松地在Python程序中进行数据库操作&#xff0c;包括查询、插入、更新、删除等操作。 以下是Psycopg2库的一些…

【图像分类】基于LIME的CNN 图像分类研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Element Plus <el-table> 组件之展开行Table在项目中使用

目录 官方样式&#xff1a; 展开前&#xff1a; 展开&#xff1a; 原始代码&#xff1a; 代码详解&#xff1a; 项目使用场景&#xff1a; 完成效果&#xff1a; 具体实现范本&#xff1a; 1.调整数据结构 2. 修改标签和数据绑定 3. JavaScript 部分导入和创建对象 …