程序功能说明:爬取百度贴吧帖子中的图片,用户输入贴吧名称和要爬取的起始和终止页数即可进行爬取。
思路分析:
一、指定贴吧url的获取
例如我们进入秦时明月吧,提取并分析其有效url如下
?后面为查询字符串,“%E7%A7%A6%E6%97%B6%E6%98%8E%E6%9C%88“是贴吧名称“秦时明月”的url编码。
这样我们就可以通过构造请求进入每一个贴吧了,代码实现如下:
importurllib
# 贴吧url前半部分url= "/f?"value= raw_input("请输入要爬取的贴吧名称:")
# 将查询字符串转换为url编码形式
key= urllib.urlencode({"kw":value})# 组合完整的贴吧url
url= url +key
# 查看完整url
print url
运行程序,这里输入“天行九歌”作为演示,可以得到天行九歌吧的完整链接如下:
这样就可以获取任意贴吧的链接了。
二、获取贴吧指定页数的链接:
我们进入天行九歌吧,取出该贴吧第2页到底4页的url,如下:
我们发现,每一页的url变化的是pn的值,依次增加50,结合上面贴吧完整的url,要想获得每一页的链接可以如下实现:
importurlliburl= "/f?"value= raw_input("请输入要爬取的贴吧名称:")
key= urllib.urlencode({"kw":value})
# 贴吧完整urlurl= url +key
begin_page= int(raw_input("请输入起始页:"))
end_page= int(raw_input("请输入终止页:"))for page in range(begin_page, end_page+1):
pn= (page-1)*50
# 组合出贴吧每一页的urlfull_url= url + "&pn=" +str(pn)
print full_url
运行程序,输入贴吧名称:“天行九歌”,再输入起始页1,终止页5,可得到如下结果:
这样我们就可以拿到贴吧每一页的链接了。
三、获取贴吧每一页中帖子的链接:
选择一个帖子,首先查看该帖子的元素得到:
端木蓉为何一直不苏醒
然后进入这个帖子取得它的完整链接:
/p/5344262338
分析可得:完整链接可由两部分组成,和/p/5344262338,后面的部分可以从页面源码中提取,使用xpath规则提取如下:
xpath提取规则://a[@class="j_th_tit"]/@href(先在浏览器中使用插件匹配,规则很多,找到合适的就行)
下面选择第二页帖子链接做如下演示
#-*- coding: utf-8 -*-
importurllib2from lxml importetree
# 贴吧第二页url
url= "/f?kw=%E5%A4%A9%E8%A1%8C%E4%B9%9D%E6%AD%8C&pn=50"request=urllib2.Request(url)
html=urllib2.urlopen(request).read()
content=etree.HTML(html)
# 匹配这一页中所以帖子链接的后半部分
link_list= content.xpath('//div[@class="t_con cleafix"]/div/div/div/a/@href')for link inlink_list:
# 组合为完整帖子链接
fulllink= "" +linkprint fulllink
运行程序,则可取该页中帖子的链接(展示部分)
这样就拿到了每个帖子的链接了。
四、获取每一个帖子中图片的链接:
进入一个帖子,找到发布的图片查看元素:
使用xpath规则提取图片链接:
xpath提取规则://img[@class="BDE_Image"]/@src
取上面第一个帖子做演示:
#-*- coding: utf-8 -*-
importurllib2from lxml importetree
# 第一个帖子的url
url= "/p/5341810557"headers= {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
request= urllib2.Request(url, headers =headers)
html=urllib2.urlopen(request).read()
content=etree.HTML(html)
# 匹配出帖子中的图片链接
link_list= content.xpath('//img[@class="BDE_Image"]/@src')for link inlink_list:print link
运行程序,取得帖子中图片链接(展示部分)
到现在为止,我们已经可以进入任意一个贴吧,获取每个贴吧指定页数的响应,并且可以拿到每个帖子中的图片链接,接下来要做的就是以图片链接发送请求获取响应文件保存下来即可。
五、保存图片到本地:
importurllib2
# 取得的图片链接
url= "/forum/w%3D580/sign=b42c88339945d688a302b2ac94c37dab/541d5d510fb30f243576ad03c395d143ac4b0352.jpg"headers= {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
request= urllib2.Request(url, headers =headers)
image=urllib2.urlopen(request).read()
# 将图片链接后10位作为图片文件名称
filename= url[-10:]
# 保存图片到本地
with open(filename,"wb") as f:
f.write(image)
运行程序,图片就会保存到当前的工作目录中。
六、完整程序
整个过程就是这样了,根据上面的分析,写出的完整程序如下:
#!/usr/bin/env python#-*- coding:utf-8 -*-
importurllibimporturllib2from lxml importetreedefloadPage(url):"""作用:根据url发送请求,获取服务器响应文件
url: 需要爬取的url地址"""headers= {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
request= urllib2.Request(url, headers=headers)
html=urllib2.urlopen(request).read()
content=etree.HTML(html)#匹配每个帖子url的后半部分
link_list = content.xpath('//a[@class="j_th_tit"]/@href')for link inlink_list:#组合为每个帖子的完整链接
fulllink = "" +link
loadImage(fulllink)defloadImage(link):"""作用:取出每个帖子里的每个图片连接
link:每个帖子的链接"""headers= {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
request= urllib2.Request(link, headers =headers)
html=urllib2.urlopen(request).read()
content=etree.HTML(html)#匹配帖子里发送的图片链接
link_list = content.xpath('//img[@class="BDE_Image"]/@src')#取出每个图片的连接
for link inlink_list:
writeImage(link)defwriteImage(link):"""作用:将图片保存到本地
link:图片连接"""headers= {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
request= urllib2.Request(link, headers =headers)
image=urllib2.urlopen(request).read()
filename= link[-10:]
with open(filename,"wb") as f:
f.write(image)print "已经成功下载"+filenamedeftiebaSpider(url, beginPage, endPage):"""作用:负责组合处理贴吧每个页面的url
url : 贴吧url的前部分
beginPage : 起始页
endPage : 结束页"""
for page in range(beginPage, endPage + 1):
pn= (page - 1) * 50fullurl= url + "&pn=" +str(pn)
loadPage(fullurl)print "谢谢使用"
if __name__ == "__main__":
kw= raw_input("请输入需要爬取的贴吧名:")
beginPage= int(raw_input("请输入起始页:"))
endPage= int(raw_input("请输入结束页:"))
url= "/f?"key= urllib.urlencode({"kw": kw})
fullurl= url +key
tiebaSpider(fullurl, beginPage, endPage)
运行程序,输入你要爬取的贴吧名称和要爬取的页数,图片就可以下载到你的工作目录下了。