? ——仅供学习使用勿作商用如有违规后果自负!!!
这几天一直在使用python爬取电影,主要目的也是为了巩固前段时间强化学习的网络爬虫,也算是一个不错的检验吧,面对众多的反爬机制,爬虫真的是一件不容易的事,但我们本着“没有爬不下来的东西,只有懒惰的程序员”的坊间箴言,在遵守有关法律法规的前提下,与反爬机制作斗争,也是一个提升自我的过程。下面言归正传,今天我们学习一下使用单线程多任务协程方式来爬取普通电影和vip电影
获得后下载m3u8,用python编写代码(代码与vip下载相同,不做重复说明)下载里面的.ts文件,合成.mp4,如果能够播放,但是时长显示错误的话,需要用ffmpeg转码。
ffmpeg -i out.ogv -vcodec h264 out.mp4
ffmpeg -i out.ogv -vcodec mpeg4 out.mp4
ffmpeg -i out.ogv -vcodec libxvid out.mp4
ffmpeg -i out.mp4 -vcodec wmv1 out.wmv
ffmpeg -i out.mp4 -vcodec wmv2 out.wmv
#-i 后面是输入文件名。-vcodec 后面是编码格式,h264 最佳,但 Windows 系统默认不安装。如果是要插入 ppt 的视频,选择 wmv1 或 wmv2 基本上万无一失。
附加选项:-r 指定帧率,-s 指定分辨率,-b 指定比特率;于此同时可以对声道进行转码,-acodec 指定音频编码,-ab 指定音频比特率,-ac 指定声道数,例如
如果不是会员,vip电影直接在主流视频完整抓包是抓不到完整的m3u8的,所以我们用http://jx.618g.com/?url=视频地址,去解析。关于解析网站值得说明的是,如果把优酷上的某个电影网址输入,找到的不一定是你想要的,但一般不会错。比如找房祖名的某部电影,然后找到的竟然是该名的外国片。所以jx.618g.com是在全网找这部关键字的电影哦,所以并非如你所想。解析网站也不是把原网页的电影给解析出来,主流的视频vip电影哪有这么容易就解析出来。
下面我们开始爬取电影
使用ffmpeg合成
ffmpeg -i "网址" -vcodec copy -acodec copy 电影.mp4
使用python下载.ts文件并合成(推荐),请看源码讲解。
conf.py文件:配置文件
import re
#‘‘‘
# n_times用于在下载上千个ts文件时,对待个别未成功下载的文件需要再次运行main完成下载
# 每次运行一次main更改一次数字
#‘‘‘
n_times=1
#‘‘‘
# 永远不变
#‘‘‘
#undo_list为未下载成功后生成的未下载序号
undo_list=‘未下载‘+str(n_times)+‘.txt‘
#new_m3u8_list为未下载成功后生成的待下载的.ts文件列表
new_m3u8_list=‘new_m3u8_list‘+str(n_times)+‘.txt‘
#‘‘‘
# 每次下载一部电影都要更改
#‘‘‘
#m3u8原始路径
path_m3u8 = ‘新扎师妹.m3u8‘
#下载地址的base目录
path_base=‘https://youku.cdn-tudou.com/20180611/6359_a2aef4b6/1000k/hls/‘
#root为电影ts文件下载目录
root = r"D:\movie\vip8"
#对某部电影匹配正则运算,找到电影序号
ret = re.compile(‘de5a(.*?).ts‘)
create_m3u8_list.py:对m3u8源文件进行提取下载列表
from conf import path_m3u8
import os
def m3u8_table(path_m3u8):
m3u8_list=path_m3u8+‘.txt‘
with open(path_m3u8,mode=‘r‘,encoding=‘utf-8‘)as f:
if not os.path.isfile(m3u8_list):
for line in f:
if ‘.ts‘ in line:
with open(m3u8_list, mode=‘a‘, encoding=‘utf-8‘)as f1:
f1.write(line)
return m3u8_list
m3u8_list=m3u8_table(path_m3u8)
m3u8_main.py:运行的主文件
import requests
import aiohttp
import asyncio
import re
import os
import time
from time import sleep
from conf import *
from create_m3u8_list import m3u8_list#无论from还是直接import都会运行那个模块的
from functools import partial# partial(偏函数)可以把函数包装成另外一个函数
start=time.time()
headers = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36‘}
num=0#计算到第几个文件
async def get_request(sem,url):
global num
async with sem:
async with aiohttp.ClientSession() as s:
async with await s.get(url,headers=headers) as response:
rep = await response.read()#read()返回的是byte类型的数据
num += 1
print(‘------------{}‘.format(num))
return rep
tasks = []
#最大并发数
sem = asyncio.Semaphore(50)
# 向回调函数传递参数
def parse(line,task):
try:
res = ret.findall(line)
ct = "%04d" % int(res[0])
rep = task.result()
abs_path = os.path.join(root, ct + ‘.ts‘)
with open(abs_path, mode=‘wb‘)as f1:
f1.write(rep)
except Exception as e:
with open(undo_list,mode=‘a‘,encoding=‘utf-8‘)as f2:
f2.write(ct+‘\n‘)
print(e)
def run(path):
with open(path,mode=‘r‘,encoding=‘utf-8‘)as f:
for line in f:
line=line.strip(‘\n‘)
if ‘http‘ not in line:
line=path_base+line
c = get_request(sem,line)
task = asyncio.ensure_future(c)
task.add_done_callback(partial(parse,line))
#还是要用回调的,传参的回调,一边下一边就能保存,比后面同步的后续处理要好,因为不需要task都完毕了才保存。
tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
def main():
run(exec_list)
with open(undo_list, mode=‘r‘, encoding=‘utf-8‘) as f3, open(m3u8_list, mode=‘r‘, encoding=‘utf-8‘)as f4, open(new_m3u8_list, mode=‘a‘, encoding=‘utf-8‘) as f5:
whole = f4.readlines()
for line in f3:
line = line.strip(‘\n‘)
f5.write(whole[int(line)])
print(time.time()-start)
if __name__ == ‘__main__‘:
# 第一遍执行文件exc_list选择m3u8_list,第二遍选择new_m3u8_list1,第三遍以此类推
if n_times==1:
exec_list=m3u8_list
else:
exec_list=‘new_m3u8_list‘+str(n_times-1)+‘.txt‘
main()
#后面不适用回调,为同步处理数据,感觉不好,一错俱错
# if __name__ == ‘__main__‘:
# run(path)
# for task in tasks:
# try:
# # 这个ct放try后面顺序就不会乱,否则,一旦有个不能下载,就一直保持连续,都不知道谁有问题不能下。
# ct += 1
# rep = task.result()
# ct1 = "%04d" % int(ct)
# abs_path = os.path.join(root,ct1+‘.ts‘)
# with open(abs_path, mode=‘wb‘)as f1:
# f1.write(rep)
# except Exception:
# print(task.cancel())
# continue
# print(time.time()-start)
m3u8_combine.py:合成ts文件为mp4格式
# 整合所有ts文件,保存为mp4格式
import os
import sys
import shutil
def tsToMp4():
print("开始合并...")
root = r"D:\Movie\vip7"
outdir = r"D:\Movie\output"
#很重要,一定要切换到目录下
os.chdir(root)
if not os.path.exists(outdir):
os.mkdir(outdir)
os.system("copy /b *.ts new.mp4")
os.system("move new.mp4 {}".format(outdir))
print("结束合并...")
tsToMp4()
如果存在普通电影爬取所说的能看而时长错误,可以使用ffmpeg转码
强烈建议大家注册为会员观看vip电影,电影爬取仅为学习使用,不可作为商业用途,产生侵权等法律问题由当事人承担
书写不易,请留有余香
原文:https://www.cnblogs.com/hypzju/p/12611395.html