Python 获取网页视频
优采云 发布时间: 2022-06-04 00:28Python 获取网页视频
前言
最近在刷剧,想着把视频搞下来顺便学一下爬虫,网上看了一些资料,最后也成功了。以下是我获取视频的过程。
创建IP池
为了防止IP被ban先建立好IP池
模拟登录
在一些视频网站上看电影可能不需要登录直接可以观看,但是这里需要要登录,所以需要先进行模拟登录。
这里可以采取selenium进行模拟登入,寻找相应元素并点击,不知道什么原因采取xpath路径寻找会找不到,所以采取css表达式进行寻找
wd.find_element_by_css_selector('div[class="action mt_15"]').click() # 点击登录按钮<br />wd.find_element_by_class_name("un-selected").click() # 勾选服务<br />wd.find_elements_by_css_selector('span[class="type-icon"]')[0].click() # 选择qq登录<br />
之后选择qq的登录方式时,账号密码登录框架被嵌套两次,需要进行跳转到对应框架才能获取对应元素
wd.switch_to.frame("_login_frame_quick_") # 进入登录框架<br />wd.switch_to.frame("ptlogin_iframe")<br />wd.find_element_by_id('switcher_plogin').click() # 选择登录方式<br />account = wd.find_element_by_id('u') # 账号<br />account.send_keys(account)<br />pd = wd.find_element_by_id('p') # 密码<br />pd.send_keys(password)<br />wd.find_element_by_css_selector('a[class="login_button"]').click() # 登录<br />
获取m3u8
常规播放方式是使用m3u8格式的ts流进行播放,只要能够截取到ts片段进行合成就可以获得整个视频,而ts链接存储在m3u8中,需要先获取m3u8文件
腾讯视频的m3u8文件是隐藏的,通过开发者模式寻找比较费时。但是腾讯视频封装在window全局对象下边,可以通过js快速获取,避免大量寻找
通过selenium执行js即可获得m3u8的下载地址从而获取m3u8
def get_m3u8(txt):<br /> r = requests.get(txt,timeout=5,proxies=proxy)<br /> with open('movies.txt','wb') as f:<br /> f.write(r.content)<br /><br />wd.execute_script('alert(PLAYER._DownloadMonitor.context.dataset.currentVideoUrl);')<br />m3u8 = wd.switch_to.alert.text<br />get_m3u8(m3u8)<br />
获取ts片段
打开m3u8文件发现里面ts片段的地址是不全的,缺少前半部分,通过验证发现缺少的前半部分链接每次刷新视频后会更改,并不是固定的所以还是需要获取,经过验证发现缺少的链接包含在m3u8链接里面,所以ts片段完整链接=m3u8的部分链接+m3u8里面记载的ts链接
def get_ts(n):<br /> with open("movies/" + str(n)+'.ts', 'wb') as f:<br /> try:<br /> r = requests.get(main_url+urls[n], timeout=5 ,proxies=proxy)<br /> r.raise_for_status()<br /> f.write(r.content)<br /> if flag == 1:<br /> failure_list.remove(n)<br /> except:<br /> if n not in failure_list:<br /> failure_list.append(n)<br /><br />main_url = '/'.join(m3u8.split('/')[0:-1])+'/'<br />urls = get_ts_url() # 存储ts链接<br />for i in tqdm(ts_list, desc="正在获取片段:"):<br /> get_ts(i,proxies=proxy,timeout=5)<br />
拼接
检查每个ts片段是否异常,当所有片段是正常的后进行拼接,从而获取到视频
# 合成ts片段<br />def get_video():<br /> files = [str(i)+'.ts' for i in range(len(os.listdir("movies/")))]<br /> if os.path.exists("movies.mp4"):<br /> os.remove("movies.mp4")<br /> for file in tqdm(files, desc="正在转换视频格式:"):<br /> if os.path.exists("movies/" + file):<br /> with open("movies/" + file, 'rb') as f1:<br /> with open("movies.mp4", 'ab') as f2:<br /> f2.write(f1.read())<br /> else:<br /> print("失败")<br /> <br /># 检查是否片段是否完好<br />def check_ts():<br /> while failure_list:<br /> print("异常片段:")<br /> print(failure_list)<br /> for i in failure_list:<br /> get_ts(i)<br /> get_video()<br />
补充
selenium会在终端显示日志,导致进度条重复出现,这里关掉日志显示
options = webdriver.ChromeOptions()<br />options.add_experimental_option('excludeSwitches', ['enable-logging'])<br />wd = webdriver.Chrome(chrome_options=options)<br />
爬取完后发现,这样爬取的视频清晰度度是默认的,不是高清的。同时,切换清晰度的按钮是隐藏的,如果通过元素寻找直接点击会报错,但是将鼠标放在视频窗口上就可以显示清晰度按钮,进而点击切换清晰度
# 切换清晰度<br />video = wd.find_element_by_css_selector('txpdiv[class="txp_shadow"]')<br />ActionChains(wd).move_to_element(video).perform() # 控制鼠标移动到视频位置<br />wd.find_elements_by_css_selector('txpdiv[class="txp_label"]')[1].click()<br />wd.find_element_by_css_selector('txpdiv[data-role="txp-ui-control-definition-list"] txpdiv:nth-of-type(2)').click() # 选择对应清晰度<br />
总结
获取ts片段时采用requests能够快速获取,而在模拟登录和获取m3u8上采取selenium比较浪费时间,效率不高,之后看看能不能采用requests代替selenium实现快速爬取。可能是反爬机制,尝试采取多线程直接拒绝访问了,所以只能采取单线程,后续看看能不能通过其他方式加快获取速度。