代码拉取完成,页面将自动刷新
#coding=utf-8
#-*- coding: UTF-8 -*-
#coder poorboy(叼毛)
#url http://www.caipiao365.vip
import urllib
import urllib2
import json
import random
import urlparse
import binascii
import base64
import os
# 访问网页的header
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}
httpBase = "https://www.toutiao.com/search_content/?"
# JS返回的数组名称
JSARRNAME = "JsArr"
class VideoItem(object):
#视频的标题
title = ""
#视频的URL 有两种如下 一种是视频源地址 一种是网页 流媒体的方式
# url: http://dianbo01.jxtvcn.com.cn/jxwlgbdst/vod/2017/12/24/df325ac6b46b4ddbb9d06bcd0dbf5c1c/h264_800k_mp4.mp4
#url: http://toutiao.com/group/6495197689683116557/
url = ""
#检查是URL看是mp4文件还是
isMp4File = False
#初始化方法
# _title 视频的标题
# _url 视频的地址
def __init__(self, _title, _url):
self.title = _title
self.url = _url
self.ClearTitleErrorStr()
#要是以.mp4结尾的url那么就是mp4文件
if self.url[-4:] == ".mp4":
self.isMp4File = True
#有时候转码可能出现特殊字符 懒得查原因就这里写个笨一点的方法
def ClearTitleErrorStr(self):
self.title = self.title.replace("?", "")
self.title = self.title.replace("%", "")
self.title = self.title.replace("`", "")
self.title = self.title.replace("'", "")
self.title = self.title.replace("$", "")
self.title = self.title.replace("*", "")
self.title = self.title.replace("^", "")
self.title = self.title.replace("&", "")
self.title = self.title.replace("(", "")
self.title = self.title.replace(")", "")
self.title = self.title.replace("\\", "")
self.title = self.title.replace("/", "")
def IsMp4(self):
return self.isMp4File
class DownVideoMgr(object):
#视频文件保存的路径
sBaseFilePath = "F:\\vDown\\"
isFileOver = False
#设置文件的保存目录
#参数:
# sPath 视频文件保存的路径
#返回值: 无
def SetDownBaseDir(self, sPath):
self.sBaseFilePath = sPath
#设置文件当本地文件存在时采用的操作
#参数:
# _isOver 当本地文件存在时采用的操作
# _isOver = True 覆盖 _isOver =False 跳过
#返回值: 无
def SetFileSaveOver(self, _isOver):
self.isFileOver = _isOver
#获取搜索URL的参数
#参数:
# serchStr 搜索的关键字
# nPages 搜索的页码
#返回值:
# strParas 通过URL编码后的查询参数
def GetParas(self, serchStr, nPages):
'''
研究了他的URL参数大致猜测的字段和意思
'''
paras = {
"offset": nPages, #记录的开始数字 0开始 0 20 40 60 具体见 count 字段 默认是每页有20条记录但是每面多多少少有些广告
"format": "json", #返回的数据类型
"keyword": serchStr, #要搜索的关键词
"autoload": "true", #html网页获取记录后是否自动显示的页面里
"count": "20", #每次请求返回的记录大小(建议和前台的页面保持一致) 我设置其他的,他们的的服务器也只每次返回20条记录
"cur_tab": "2", #前面页面的标签(可以用2不用管他 和前台的页面保持一致)
"from": "search_tab", #提交搜索的前面页面的表单名(不用管他就用这个 也就是cur_tab 2)
"callback": JSARRNAME #Json数据返回后前台页面JS代码里数组的名字这个我改了一个 他的太长了点 看不习惯 @_@
}
strParas = urllib.urlencode(paras)
return strParas
#获取打开页面的结果
#参数:
# url 打开网页的地址
#返回值:
# 成功 打开页面的结果
# 失败 空字符串
def GetWebRet(self, url):
htmlStr = ""
try:
request = urllib2.Request(url, headers=headers)
response = urllib2.urlopen(request)
htmlStr = response.read()
except Exception as e:
print e
bRet = False
htmlStr = ""
return htmlStr
#获取搜索的结果
#参数:
# seachKey 搜索的关键词
# nPage 第几页
#返回值:
# 成功 搜索的JSON结果
# 失败 空字符串
def GetSeachRet(self, seachKey, nPage):
url = httpBase + self.GetParas(seachKey, nPage)
jsonStr = self.GetWebRet(url)
if (len(jsonStr) > 10):
jsonStr = jsonStr[len(JSARRNAME) + 1:-1]
return jsonStr
#根据KEY返回JSON对象的里值
# jsObj json对象
# key json对象的key
#参数:
# jsObj json对象
# key json对象的key
#返回值:
# 成功 要是KEY存在就返回对应的值
# 失败 要是KEY不存在返回空字符串
def GetJsonItemData(self, jsObj, key):
if jsObj.has_key(key):
return jsObj[key]
return ''
#根据JSON字符串获取视频记录信息
#参数:
# jsonStr json字符串
#返回值:
# VideoItem 列表
def GetVItem(self, jsonStr):
jsObj = json.loads(jsonStr)
itemsize = len(jsObj['data'])
videoList = []
for i in range(0, itemsize):
tmpJs = jsObj['data'][i]
#.decode('raw_unicode-escape').encode('utf-8')
title = u"" + self.GetJsonItemData(tmpJs, 'title')
url = u"" + self.GetJsonItemData(tmpJs, 'url')
if url.find("wukong.com/question") > 0:
url = ""
if len(title) > 0 and len(url) > 0 :
tItem = VideoItem(title, url)
videoList.append(tItem);
return videoList
#获取搜索的结果
#参数:
# seachKey 搜索的关键词
# nStart 从第几条记录开始获取
#返回值:
# VideoItem 列表
def GetVideoItem(self, seachKey, nStart):
jsonStr = self.GetSeachRet(seachKey, nStart)
return self.GetVItem(jsonStr)
#根据url保存文件
#参数:
# url mp4文件的URL
# loactFile 本地保存的路径
#返回值:
# True 下载成功
# False 下载失败
def SaveUrl2File(self, url, loactFile):
bRet = True
try:
request = urllib2.Request(url, headers=headers)
response = urllib2.urlopen(request)
data = response.read()
with open(loactFile, "wb") as code:
code.write(data)
except Exception as e:
print e
bRet = False
return bRet
#根据流媒体的网页地址获取流媒体的srcID
#参数:
# url 流媒体的网页地址
#返回值:
# True 返回流媒体的src
# False 返回空字符串
def GetStreamingVideoID(self, url):
htmlStr = self.GetWebRet(url)
if len(htmlStr) < 5:
return "";
strID = ""
strFindSrart = "videoid"
nStart = htmlStr.find(strFindSrart)
nEnd = -1
if nStart > 0:
nEnd = htmlStr.find(",", nStart)
if nEnd > 10:
strID = htmlStr[nStart+len(strFindSrart)+2 : nEnd-1]
return strID
#获取随机数
#参数: 无
#返回值:
# 随机数字符串
def GetRandPara(self):
randStr = bytes(random.random()) [2:]
return randStr
#获取CRC检验右移的值
#参数:
# val 右移的值
# n 右移的值的位数
#返回值:
# 右移动的结果
def GetCrcValue(self, val, n):
return val >> n if val >= 0 else (val + 0x100000000) >> n
#根据视频的ID获取真实播放地址的API地址
#参数:
# vID 流媒体的ID
# vID 可以通过 GetStreamingVideoID 这个方法获取
#返回值:
# 获取真实播放地址的API地址
def GetStreamAPIUrl(self, vID):
r = self.GetRandPara()
jsUrl = 'http://i.snssdk.com/video/urls/v/1/toutiao/mp4/%s' % vID
n = urlparse.urlparse(jsUrl).path + '?r=' + r
c = binascii.crc32(n)
s = self.GetCrcValue(c, 0)
return jsUrl + '?r=' + r + '&s=' + bytes(s)
# 获取真实播放地址的API获取真实的流媒体播放地址
#参数:
# url 流媒体的获取API的地址
# url 可以通过 GetStreamAPIUrl 这个方法获取
#返回值:
# True 流媒体真实地址
# False 空字符串
def GetStreamSrc(self, url):
vID = self.GetStreamingVideoID(url)
src = self.GetStreamAPIUrl(vID)
jsonStr = self.GetWebRet(src)
vUrl = ""
strFindSrart = "main_url"
nStart = jsonStr.find(strFindSrart)
nEnd = -1
if nStart > 0:
nEnd = jsonStr.find(",", nStart)
if nEnd > 10:
vUrl = jsonStr[nStart+len(strFindSrart)+2 : nEnd-1]
videourl = base64.b64decode(vUrl)
return videourl
#根据流媒体的地址下载流媒体文件
#参数:
# url 流媒体的Src地址
# file 本地保存的路径
#返回值:
# True 下载成功
# False 下载失败
def DownStreamVideo(self, url, file):
videoUrl = self.GetStreamSrc(url)
return self.SaveUrl2File(videoUrl, file)
#根据VideoItem下载视频
#参数:
# vItem 流媒体信息
# 可以通过 GetVideoItem 方法获取
#返回值:
# True 下载成功
# False 下载失败
def DownVideoItem(self, vItem):
fileSavePaht = self.sBaseFilePath + vItem.title.encode("gbk") + ".mp4"
if os.path.exists(fileSavePaht):
if self.isFileOver:
try:
os.remove(fileSavePaht)
except Exception as e:
print e
return False
else:
return True
if vItem.IsMp4():
return self.SaveUrl2File(vItem.url, fileSavePaht)
else:
return self.DownStreamVideo(vItem.url, fileSavePaht)
def Test():
DowObj = DownVideoMgr()
keyS = "儿童舞蹈教学"
vArrList = []
for i in range(0, 201, 20):
vItem = DowObj.GetVideoItem(keyS, i)
for r in vItem :
vArrList.append(r)
for r in vArrList :
DowObj.DownVideoItem(r)
if __name__ == '__main__':
Test()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。