目录
百度贴吧图片和视频文件爬取程序
1.需求分析
进入百度贴吧,搜索周杰伦,进入周杰伦吧。我们的目的是爬取图片文件和视频。下面是首页文件,如果我们要爬取图片或视频文件的话,第一步是爬取该页面下的所有帖子的url,进入到这些帖子后,再进行图片和视频爬取。
2.url分析
1)百度贴吧首页url分析
经过初步分析,我发现百度贴吧的url为:http://tieba.baidu.com/f?kw=周杰伦pn=0
kw是搜索内容,pn是页码,第一页为0,第二页为50,所以页码的公式为pn=(页数-1)*50
2)帖子url分析
经分析,发现帖子的链接只有一小段,百度采用的是相对路径的方式。
点击进入帖子,发现帖子的Url为:http://tieba.baidu.com/p/6130726976
也就是说帖子完整的url:http://tieba.baidu.com/+帖子href属性里的值
3.Xpath分析
如果对Xpath不熟的可以去看我另一篇文章,里面有Xpath的教学:https://blog.csdn.net/ck784101777/article/details/104291634
分析完url后,接下来分析如何提取贴子的url和图片、视频的url。
我是通过右键进入检查页面,来进行分析的。按图中步骤来做就可。
1)帖子Xpath分析
进过分析,很容易的得帖子的Xpath://div[@class="threadlist_title pull_left j_th_tit"]/a/@href
只需要定位到a标签的父节点div的class属性值,再提取a的href属性值即可
2)图片Xpath分析
分析后得出Xpath://div[@class="d_post_content j_d_post_content clearfix"]/img[@class="BDE_Image"]/@src
3)视频Xpath分析
一开始我写Xpath时的时候,是按照下图来写的,写出来的格式为://div[@class="video_src_wrap_main"]/video/@src
结果发现死活爬不到。然后我去分析响应源码。
发现在拿到响应文件后,视频格式有变化,按照这个变化,我写出的Xpath为:
//div[@class="video_src_wrapper"]/embed/@data-video
总结:
1.帖子Xpath://div[@class="threadlist_title pull_left j_th_tit"]/a/@href
2.图片Xpath://div[@class="d_post_content j_d_post_content clearfix"]/img[@class="BDE_Image"]/@src
3.视频Xpath://div[@class="video_src_wrapper"]/embed/@data-video
4.程序设计
程序整体的结构如下:
1.download_srcs()函数:该函数为核心函数,它首先把每个帖子的url获取到,然后进入到每个帖子去爬图片和视频
2.save_local()函数:这个函数时把图片和视频文件下载到本地,由download_srcs()调用
3.get_html()函数:功能函数,作用是获取html页面内容
4.get_Xpath()函数:功能函数,作用是获取xpath的匹配的列表
5.run()函数:启动函数,为程序的入口
from lxml import html
from urllib import parse
import random
import time
import requests
class BaiduImgandVedio_spider(object):
def __init__(self):
self.url="http://tieba.baidu.com/f?kw={}&pn={}"
self.headers="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
self.dir="C:\\Users\\Administrator\\Desktop\\新建文件夹\\"
#获取html页面的内容
def get_html(self,url):
html=requests.get(url=url,headers={"User-Agent":self.headers},timeout=3).text
return html
#获取xpath封装的结果
def get_Xpath(self,rep,xpath_regex):
p=html.etree.HTML(rep)
result=p.xpath(xpath_regex)
return result
#下载图片或视频到本地
def download_srcs(self,url):
html=self.get_html(url)
#这里有一个坑,xpath无法匹配注释文件里的的内容,我们下载的文件是带注释的,所以这里去除注释
html=html.replace("<!--","")
#获取帖子的url列表
xpath_tiezi='//div[@class="t_con cleafix"]/div/div/div/a/@href'
tiezi_lists=self.get_Xpath(html,xpath_tiezi)
#循环遍历被一个帖子
for i in tiezi_lists:
#获取到的uri类似p/6491314161,所以还要进行拼接
tiezi_url="http://tieba.baidu.com/"+i
tiezi_html=self.get_html(tiezi_url)
tiezi_html=tiezi_html.replace("<!--","")
#图片和视频的xpath
xpath_imgorvedio='//img[@class="BDE_Image"]/@src | //div[@class="video_src_wrapper"]/embed/@data-video'
#调用Xpath解析方法,获得图片和视频的url
imgorvedio_urls=self.get_Xpath(tiezi_html,xpath_imgorvedio)
#下载到本地
self.save_local(imgorvedio_urls)
#保存到本地
def save_local(self,urls):
for i in urls:
imgordedio_html=requests.get(url=i,headers={"User-Agent":self.headers},timeout=10).content
#切割后10位
filename=i[-10:]
dir=self.dir+filename
print(dir)
with open(dir,"wb") as f:
f.write(imgordedio_html)
time.sleep(random.randint(0,1))
print(filename,"下载成功")
#函数入口
def run(self):
word=input("请输入关键词:")
begin=int(input("请输入起始页:"))
end=int(input("请输入终止页:"))
#字符转编码
name=parse.quote(word)
for i in range(begin,end):
#获取页码数
i=(begin-1)*50
url=self.url.format(name,i)
#调用download函数
self.download_srcs(url)
if __name__=="__main__":
spdier=BaiduImgandVedio_spider()
spdier.run()
效果:
5.坑点
1)样式是变化的,xpath可能失效
本程序有很多坑点,最大的坑点就在于xpath,由于百度贴吧的样式(class属性)不是一成不变的,我可能今天这么写可以成功,但是以后改动后这个程序就爬不到了,所以如果你执行这个程序没有爬到数据,需要自己去改xpath,分析流程请按照我文章所讲的去做。
2)垃圾图片
另外一个坑点就在于爬取到的图片和视频有很多垃圾图片,这个是没办法的,xpath的匹配结果是模糊匹配,不可能帮你识别图片是否垃圾图片,这里指的垃圾图片是与内容无关的,比如我想爬周杰伦的图片却给我爬出一些广告图片。
3)访问被拒
访问被拒有可能是你的User-Agent问题,这里推荐用一个动态的User-Agent,也就是不要用一成不变的,你可以做一个User-Agent池,每次发请求时用一个随机数获取池中的一条Agent。
如果你的ip因为爬虫被封了,你可以尝试用代理ip去爬,网上代理ip一大堆,当然,如果是免费的代理ip是非常不好用的,如果你想用好一点的代理ip,可以去专门卖代理ip的网站上去买,价格不贵。