声明:我写的所有文章都是发在博客园的,我看到其他复制粘贴过去的 连个出处也不写,直接打上自己的水印。。。真是没的说了。

前言:前段时间搞了一些爬视频的项目,代码都写好了,这里写文章那就在来重新分析一遍吧。有不好的地方 莫见怪 : )

环境:python2.7 + win10

开始先说一下,访问youtube需要科学上网,请自行解决,最好是全局代理。

ok,现在开始,首先打开网站观察

网站很干净清爽,这次做的是基于关键字搜索来爬那些相关视频,这样就能很好的分类了,若输入中文搜索,那结果也一般都是国内视频,英文的话 那就是国外的。

这里先来测试中文的 ,输入''搞笑'',搜出来很多视频,也可以根据条件筛选,YouTube视频链接很有规律,都是这种https://www.youtube.com/watch?v=v_OVBHGwOaU,只有后面的 v值不一样,这里就叫id吧。

ok,先从最简单的开始,查看网页源代码看看这些视频链接是否都是在里面,我睁大了我的24k单身狗的眼睛找出来了。。。看了一下,视频信息全在这个<script>标签里面。

既然如此,那就直接上正则表达式来匹配

  1. "url":"/watch\?v=(.*?)","webPageType"

这样就能匹配出ID来。但是 这好像只有第一页的视频,那第二页的呢,经常观察,此方法不行,视频翻页是基于ajax请求来的,源码里面的信息始终都是第一页的数据,ok 那既然这样,我们来分析ajax请求,我喜欢用谷歌浏览器,打开开发者工具,network,来抓包。

鼠标一直往下拉,会自动请求,是个post请求,一看就是返回的视频信息。

看到这里很高兴,离胜利已经不远了。但,我们先来看下headers 以及发送的post参数,看了之后 就一句 wtf。。。

一万个羊驼在奔腾,我把那些加密的参数都标记了,前后端交互,既然是发过去的数据,那肯定已经在前端产生了,至于什么产生的,那就要一步一步分析来了,最后。对 我没有分析出来。。。刚开始挨着挨查看js文件,参数的确是在js里面产生的,但。。。tmd写的太复杂了。。。能力有限,解决不了。难道就这样放弃了吗。肯定不会,不然 各位也不会看到这篇文章了。于是,我灵机一动,在地址栏里面输入&page=  结果,真的返回视频了。。。卧槽  哈哈哈,我当时真是很开心呢。因为前端页面上并没有翻页按钮,没想到竟然还真的可以这样翻页。。。哈哈

既然这都被我猜出来了,那思路就很清晰了,翻页--获得源代码-- 正则匹配 --就可以批量得到视频链接了,然后去重后 在想办法直接通过这个链接去下载。于是,一阵百度 谷歌 找到很多方法,也找到很多api,ok 那就不必要重复造轮子,直接拿来用吧。

有一个开源项目youtube-dl 在github上 是个命令行的应用,安装之后,他是这样的。

  1. youtube-dl -F https://www.youtube.com/watch?v=_iupLGTX890

这样就能直接分析出所有视频格式的信息,然后通过id 就可以下载下来了。是很好用的一个工具。

在代码里面怎么使用呢,直接调用cmd命令就行了,但是。经过我测试发现呢,批量下载时候,老是有一些视频没有下载完整,所以 我就没用这个方法了,在国外网站上找到一个api 还蛮不错。

怎么找 怎么使用api 我就不用介绍了吧,等会直接贴代码,大家一看便知。

这里在说下,当我输入关键字是英文的话,搜出来的结果全部是英文的,于是 我就下载成功后,保存文件 翻译一下他的标题。翻译成中文的,我去找翻译,最后就用金山词霸了,如果使用官方api的话,好像也有收费。。那不行,我要直接爬页面,于是,我就直接还是爬他的翻译页面,提交英文,返回中文,解析网页,正则匹配出来。就这样 嘿嘿嘿。。

ok。说了这么多了 现在上代码。

  1. # -*-coding:utf-8-*-
  2. # author : Corleone
  3. from bs4 import BeautifulSoup
  4. import lxml
  5. import Queue
  6. import requests
  7. import re,os,sys,random
  8. import threading
  9. import logging
  10. import json,hashlib,urllib
  11. from requests.exceptions import ConnectTimeout,ConnectionError,ReadTimeout,SSLError,MissingSchema,ChunkedEncodingError
  12. import random
  13.  
  14. reload(sys)
  15. sys.setdefaultencoding('gbk')
  16.  
  17. # 日志模块
  18. logger = logging.getLogger("AppName")
  19. formatter = logging.Formatter('%(asctime)s %(levelname)-5s: %(message)s')
  20. console_handler = logging.StreamHandler(sys.stdout)
  21. console_handler.formatter = formatter
  22. logger.addHandler(console_handler)
  23. logger.setLevel(logging.INFO)
  24.  
  25. q = Queue.Queue() # url队列
  26. page_q = Queue.Queue() # 页面
  27.  
  28. def downlaod(q,x,path):
  29. urlhash = "https://weibomiaopai.com/"
  30. try:
  31. html = requests.get(urlhash).text
  32. except SSLError:
  33. logger.info(u"网络不稳定 正在重试")
  34. html = requests.get(urlhash).text
  35. reg = re.compile(r'var hash="(.*?)"', re.S)
  36. result = reg.findall(html)
  37. hash_v = result[0]
  38. while True:
  39. data = q.get()
  40. url, name = data[0], data[1].strip().replace("|", "")
  41. file = os.path.join(path, '%s' + ".mp4") % name
  42. api = "https://steakovercooked.com/api/video/?cached&hash=" + hash_v + "&video=" + url
  43. api2 = "https://helloacm.com/api/video/?cached&hash=" + hash_v + "&video=" + url
  44. try:
  45. res = requests.get(api)
  46. result = json.loads(res.text)
  47. except (ValueError,SSLError):
  48. try:
  49. res = requests.get(api2)
  50. result = json.loads(res.text)
  51. except (ValueError,SSLError):
  52. q.task_done()
  53. return False
  54. vurl = result['url']
  55. logger.info(u"正在下载:%s" %name)
  56. try:
  57. r = requests.get(vurl)
  58. except SSLError:
  59. r = requests.get(vurl)
  60. except MissingSchema:
  61. q.task_done()
  62. continue
  63. try:
  64. with open(file,'wb') as f:
  65. f.write(r.content)
  66. except IOError:
  67. name = u'好开心么么哒 %s' % random.randint(1,9999)
  68. file = os.path.join(path, '%s' + ".mp4") % name
  69. with open(file,'wb') as f:
  70. f.write(r.content)
  71. logger.info(u"下载完成:%s" %name)
  72. q.task_done()
  73.  
  74. def get_page(keyword,page_q):
  75. while True:
  76. headers = {
  77. 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0'
  78. }
  79. page = page_q.get()
  80. url = "https://www.youtube.com/results?sp=EgIIAg%253D%253D&search_query=" + keyword + "&page=" + str(page)
  81. try:
  82. html = requests.get(url, headers=headers).text
  83. except (ConnectTimeout,ConnectionError):
  84. print u"不能访问youtube 检查是否已翻墙"
  85. os._exit(0)
  86. reg = re.compile(r'"url":"/watch\?v=(.*?)","webPageType"', re.S)
  87. result = reg.findall(html)
  88. logger.info(u"第 %s 页" % page)
  89. for x in result:
  90. vurl = "https://www.youtube.com/watch?v=" + x
  91. try:
  92. res = requests.get(vurl).text
  93. except (ConnectionError,ChunkedEncodingError):
  94. logger.info(u"网络不稳定 正在重试")
  95. try:
  96. res = requests.get(vurl).text
  97. except SSLError:
  98. continue
  99. reg2 = re.compile(r"<title>(.*?)YouTube",re.S)
  100. name = reg2.findall(res)[0].replace("-","")
  101. if u'\u4e00' <= keyword <= u'\u9fff':
  102. q.put([vurl, name])
  103. else:
  104. # 调用金山词霸
  105. logger.info(u"正在翻译")
  106. url_js = "http://www.iciba.com/" + name
  107. html2 = requests.get(url_js).text
  108. soup = BeautifulSoup(html2, "lxml")
  109. try:
  110. res2 = soup.select('.clearfix')[0].get_text()
  111. title = res2.split("\n")[2]
  112. except IndexError:
  113. title = u'好开心么么哒 %s' % random.randint(1, 9999)
  114. q.put([vurl, title])
  115. page_q.task_done()
  116.  
  117. def main():
  118. # 使用帮助
  119. keyword = raw_input(u"请输入关键字:").decode("gbk")
  120. threads = int(raw_input(u"请输入线程数量(建议1-10): "))
  121. # 判断目录
  122. path = 'D:\youtube\%s' % keyword
  123. if os.path.exists(path) == False:
  124. os.makedirs(path)
  125. # 解析网页
  126. logger.info(u"开始解析网页")
  127. for page in range(1,26):
  128. page_q.put(page)
  129. for y in range(threads):
  130. t = threading.Thread(target=get_page,args=(keyword,page_q))
  131. t.setDaemon(True)
  132. t.start()
  133. page_q.join()
  134. logger.info(u"共 %s 视频" % q.qsize())
  135. # 多线程下载
  136. logger.info(u"开始下载视频")
  137. for x in range(threads):
  138. t = threading.Thread(target=downlaod,args=(q,x,path))
  139. t.setDaemon(True)
  140. t.start()
  141. q.join()
  142. logger.info(u"全部视频下载完成!")
  143.  
  144. main()

在这里在说一下,我当时用的win10 所有编码全是gbk的,若在linux上面跑,请自行修改。也是多线程下载的,默认下载目录 d:\youtube 然后会根据关键字在创建子目录,视频都放在里面。对了 还有我代码里面用筛选了,只爬1天之内更新的。每天爬一遍即可。

来测试一下。下载的时候 就是考验网速的时候了,网不好了,可能会出现一些我没捕获的异常。。。可能是我找的fq服务器网速还行。。

ok 到这里整篇文章就结束了,写文章都快弄了一个小时了。。不容易呢 :-

我的github地址 https://github.com/binglansky/spider

嘿嘿,欢迎一块学习交流 :) ~~~

python爬取youtube视频 多线程 非中文自动翻译的更多相关文章

  1. python爬取快手视频 多线程下载

    就是为了兴趣才搞的这个,ok 废话不多说 直接开始. 环境: python 2.7 + win10 工具:fiddler postman 安卓模拟器 首先,打开fiddler,fiddler作为htt ...

  2. python爬取豆瓣视频信息代码

    目录 一:代码 二:结果如下(部分例子)   这里是爬取豆瓣视频信息,用pyquery库(jquery的python库). 一:代码 from urllib.request import quote ...

  3. python爬取百思不得姐视频

    # _*_ coding:utf-8 _*_ from Tkinter import * from ScrolledText import ScrolledText import urllib #im ...

  4. python 爬取bilibili 视频信息

    抓包时发现子菜单请求数据时一般需要rid,但的确存在一些如游戏->游戏赛事不使用rid,对于这种未进行处理,此外rid一般在主菜单的响应中,但有的如番剧这种,rid在子菜单的url中,此外返回的 ...

  5. python 爬取bilibili 视频弹幕

    # -*- coding: utf-8 -*- # @author: Tele # @Time : 2019/04/09 下午 4:50 # 爬取弹幕 import requests import j ...

  6. 【Python爬虫案例学习2】python多线程爬取youtube视频

    转载:https://www.cnblogs.com/binglansky/p/8534544.html 开发环境: python2.7 + win10 开始先说一下,访问youtube需要那啥的,请 ...

  7. 用 pytube 爬取 youtube 视频

    这个方法比直接用浏览器插件逼格高点 1. 简介 需要用到 pytube 这个第三方库:https://github.com/nficano/pytube 这里只是把这个页面捡重要部分翻译了一下. py ...

  8. python爬取网站视频保存到本地

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: Woo_home PS:如有需要Python学习资料的小伙伴可以加点 ...

  9. 2019-02-09 python爬取mooc视频项目初级简单版

    今天花了一下午时间来做这东西,之前没有自己写过代码,50几行的代码还是查了很多东西啊,果然学起来和自己动起手来完全是两码事. 方案:requests库+正则表达式提取视频下载链接+urlretriev ...

随机推荐

  1. nginx截获客户端请求

    使用nginx可以直接截获客户端请求,以下是最近收集的一些判断截获的信息的配置,为查看方便记录如下: 1.根据UA和cookie判断当前是移动端还是PC端访问: if ($http_host !~ & ...

  2. client / page / offset / screen X / Y

    1.clientX / clientY 相对于可视窗口左上角,不包括菜单栏与滚动条 2.pageX / pageY 相对于网页左上角,不包括菜单栏,包括滚动条 3.offsetX / offsetY ...

  3. Hexo博客框架

    https://hexo.io/docs/#What-is-Hexo hexo博客应用1 hexo博客应用2 Spark Streaming 消费kafka到HDFS 搭建篇-使用Github-hex ...

  4. Python 中的闭包

    通常来说,函数中的局部变量在函数调用结束的时候不能再被引用,所分配的空间也会被回收. 但是通过闭包这种技术,函数调用结束了,它的局部变量的值还可以保存在闭包里. 试举一例: def make_adde ...

  5. return的新思考

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  6. 一个简单的定时表达式(HH:mm:ss)解析

    前言 为客户开发了一个日志监控程序,监听各频道是否正常工作.其中有一个功能是这样的,当所有频道正常运行一段时间后,语音提示值班人员系统运行正常.一开始,想法比较简单,设置了一个变量,在线程不断轮询的过 ...

  7. js获取某个日期所在周周一的日期

    第一次写,做个小笔记. 第一步:获取该日期的星期数: 第二步:在该日期上减去他的星期数再减1,(注:星期日获取到的星期数是0): 下面是具体代码: function GetMonday(dd) { v ...

  8. JAVA多线程与并发学习总结

    1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...

  9. js随机出现2个数字

    1和2 随机出现 <script type="text/javascript"> $(function(){ if (Math.random()>0.5) { c ...

  10. 4.1 PCIe总线的基础知识

    与PCI总线不同,PCIe总线使用端到端的连接方式,在一条PCIe链路的两端只能各连接一个设备,这两个设备互为是数据发送端和数据接收端.PCIe总线除了总线链路外,还具有多个层次,发送端发送数据时将通 ...