1 页面分析
百思不得姐视频地址http://www.budejie.com/video/
看到这个地址的时候我们首先分析,这个地址的多页是如何实现的?访问其他页面时链接是怎么样的?所以我们直接点击页面2,然后查看请求地址的变化如下
2 数据查找
2.1 页面结构分析
通过页面结构,我们可以看到每个视频部分都是结构相同的块组成的。
2.2 数据查找
我们使用Chrome浏览器查看每块数据的大致结构,也可以通过查看源码,搜索关键字来查看页面源码,找到我们需要使用的字段进行匹配解析。
2.2.1 开发工具查看元素
2.2.2 页面源码查看代码结构
Mac 用cmd+f命令进行搜索关键字,找到第一条数据,分析结构,准备取数据。
3 获取有效信息
3.1 获取页面源码
# 请求数据
def get_response(url):
# 为了防止被网站禁止访问,携带浏览器参数,假装浏览器请求
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
# 取出返回的数据
response = requests.get(url=url,headers=headers).content
return response
3.2 通过bs4模块解析html数据
通过bs4模块进行数据匹配,解析出有效数据。
# 通过返回的网页数据,过滤出文件名称和MP4路径
def get_content(html):
# 通过bs4框架进行解析,这里用内置的默认解析器html.parser,也可以使用lxml解析器,需要安装
soup = BeautifulSoup(html,"html.parser")
# 获取每块的数据
cont = soup.select(".j-r-list-c")
# 定义一个数组存放匹配出的名称和MP4地址
urlList = []
for item in cont:
# 查找第一个a标签的内容,作为我们后面保存MP4的文件名
name = item.find('a').text
# 查找MP4连接所在位置,通过data-mp4属性值取出
pmUrl = item.select('.j-video')[0].get('data-mp4')
# 以元祖的形式添加到数组
urlList.append((name,pmUrl))
return urlList
3.3 通过threading模块,异步下载视频
# 拼接MP4保存的路径和文件名,这里用多线程的方法
def get_mp4_url(movieList):
'''
判断当前脚本所在路径是否存在picture文件夹,这里用os模块,os.getcwd()获取当前文件的绝对路径
使用os模块的该方法不用考虑所在系统是Mac还是windows
'''
filePath = os.path.join(os.getcwd(),'picture')
# 判断路径是否存在,不存在则创建路径
if not os.path.exists(filePath):
print '路径不存在'
os.makedirs(filePath)
# 取出每个MP4的名称和路径的元祖
for item in movieList:
# 判断路径是否存在,不存在则跳转到下一个
if item[1] == None:
continue
# 判断要使用的名称是否过长,如果超过30的话,我们就截取,因为文件名过长保存的时候会报错
nameStr = item[0].strip() if len(item[0]) < 30 else item[0].strip()[:27] + '...'
# 拼接文件的绝对路径
mvPath = os.path.join(filePath,'%s.%s' % (nameStr.strip(),item[1][-3:]))
'''
通过多线程的方式下载MP4文件,增加下载速度
'''
thr = threading.Thread(target=save_mp,args=(mvPath,item[1]))
# 启动线程
thr.start()
def save_mp(mvPath,url):
'''
保存MP4文件
'''
response = get_response(url) #调用方法返回MP4文件的二进制流数据
# 通过文件写入的方式保存成文件
with open(mvPath,'wb') as fp:
fp.write(response)
4 程序完成源码
'''
Created by swh on 2017.09.12
'''
#_*_coding:utf-8_*_
import requests
import re
from bs4 import BeautifulSoup
import threading
import os
# 请求数据
def get_response(url):
# 为了防止被网站禁止访问,携带浏览器参数,假装浏览器请求
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
# 取出返回的数据
response = requests.get(url=url,headers=headers).content
return response
# 通过返回的网页数据,过滤出文件名称和MP4路径
def get_content(html):
# 通过bs4框架进行解析,这里用内置的默认解析器html.parser,也可以使用lxml解析器,需要安装
soup = BeautifulSoup(html,"html.parser")
# 获取每块的数据
cont = soup.select(".j-r-list-c")
# 定义一个数组存放匹配出的名称和MP4地址
urlList = []
for item in cont:
# 查找第一个a标签的内容,作为我们后面保存MP4的文件名
name = item.find('a').text
# 查找MP4连接所在位置,通过data-mp4属性值取出
pmUrl = item.select('.j-video')[0].get('data-mp4')
# 以元祖的形式添加到数组
urlList.append((name,pmUrl))
return urlList
# 拼接MP4保存的路径和文件名,这里用多线程的方法
def get_mp4_url(movieList):
'''
判断当前脚本所在路径是否存在picture文件夹,这里用os模块,os.getcwd()获取当前文件的绝对路径
使用os模块的该方法不用考虑所在系统是Mac还是windows
'''
filePath = os.path.join(os.getcwd(),'picture')
# 判断路径是否存在,不存在则创建路径
if not os.path.exists(filePath):
print '路径不存在'
os.makedirs(filePath)
# 取出每个MP4的名称和路径的元祖
for item in movieList:
# 判断路径是否存在,不存在则跳转到下一个
if item[1] == None:
continue
# 判断要使用的名称是否过长,如果超过30的话,我们就截取,因为文件名过长保存的时候会报错
nameStr = item[0].strip() if len(item[0]) < 30 else item[0].strip()[:27] + '...'
# 拼接文件的绝对路径
mvPath = os.path.join(filePath,'%s.%s' % (nameStr.strip(),item[1][-3:]))
'''
通过多线程的方式下载MP4文件,增加下载速度
'''
thr = threading.Thread(target=save_mp,args=(mvPath,item[1]))
# 启动线程
thr.start()
def save_mp(mvPath,url):
'''
保存MP4文件
'''
response = get_response(url) #调用方法返回MP4文件的二进制流数据
# 通过文件写入的方式保存成文件
with open(mvPath,'wb') as fp:
fp.write(response)
if __name__ == '__main__':
'''
2017-09-12作者抓取数据的时候实测共有50页数据,下面是多页请求,
'''
# for i in range(1,51):
# print i
# urlStr = 'http://www.budejie.com/video/%s' % str(i)
# html = get_response(urlStr)
# ll = get_content(html)
# get_mp4_url(ll)
'''
** 由于我们这里仅用于测试,所以我们之抓取一页
** 链接最后的数字表示抓取的数据页码,由于首页的1可以不写,也可以写上
** 为了大家更好的理解多页的表示,这里我们仅抓取一页,并且链接后面写有页码1
'''
urlStr = 'http://www.budejie.com/video/1'
html = get_response(urlStr)
ll = get_content(html)
get_mp4_url(ll)
5 执行结果