python网络爬虫入门(二)——百度贴吧

来源:互联网 发布:wifi连不上网络 有信号 编辑:程序博客网 时间:2024/05/18 02:29

前面爬完了糗事百科,接下来看看百度贴吧。

可是光光获取评论文字也是忒无聊了,咱们来点图片。

然鹅,找哪儿的图好吶,翻来覆去,一个偶然的机会,让我看到了这个:

                


机智的我灵机一动,为什么创建这个“旅行吧”呀,从事物发展的规律来说,就是方便大伙儿各种晒图各种秀啊微笑

能拿来晒的东西,敢情应该不会差到哪去(至少比一般的百度图片要好一些吧)


                                                                                        


好了不多胡扯回归正题,几行代码,带足不出户的你,走遍万水千山!

先随便搜了个贴,好吧就是这个了

         



开发环境和之前一样。

一、目标

1、获取帖子标题、总页数、评论、图片

2、图片写入文件并保存

3、将各种信息实现打印(也算测试追踪)

4、输入帖子号便能实现以上操作(即亦适用于其它帖子)


二、步骤:

1、获取源码。这个简单,用requests的get请求方式即可。这里设置了random.randint()获取随机数,在一堆范围中获取user_agent,主要是为了伪装防止网站认出是爬虫而限制抓取。至于这一堆user_agents,额,网上搜的哈哈~

    def getSource(self,url):        user_agents=['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0','Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533+ \(KHTML, like Gecko) Element Browser 5.0','IBM WebExplorer /v0.94', 'Galaxy/1.0 [en] (Mac OS X 10.5.6; U; en)','Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)','Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14','Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) \Version/6.0 Mobile/10A5355d Safari/8536.25','Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) \Chrome/28.0.1468.0 Safari/537.36','Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; TheWorld)'         index=random.randint(0,9)        user_agent=user_agents[index]        headers = {'User_agent': user_agent}        html=requests.get(url,headers=headers)        return html.text


2、获取标题、总页数、评论

标题的正则

pattern=re.compile('<h1.*?title.*?>(.*?)</h1>',re.S)items=re.search(pattern,result)

页数的正则

pattern=re.compile('<ul.*?l_posts_num.*?<span class="red">(.*?)</span>',re.S)items=re.search(pattern,result).group(1)

评论的正则

pattern=re.compile('<a data-field.*?p_author_name.*?">(.*?)</a>.*?<div id="post_content_.*?>(.*?)</div>',re.S)items=re.findall(pattern,result)


3、获取晒图。BeautifulSoup唯美汤神器登场,首先想到find_all()搜'img'标签,得到如下



龙蛇混杂呀,不仅包括各种旅行晒图,还有链接中包含'head'的头像图,含'emoticon'的表情图等等,宝宝内心是崩溃哒。

如何洗出我们想要的内容呢?

别着急,仔细观察这些个链接,逐个点开一试就会发现,凡是属于'晒图'的,接带有属性class='BDE_Image'。

我的天,直接find_all()限定范围,再循环打出item['src'],分分钟搞定链接!要有多简单就有简单,最后将链接保存至一个list中。




4、创建目录。用到makedirs(),值得注意的是,如果想将文件夹创建至非系统默认的地方,需要用到chdir()来更改环境变量。


5、保存晒图。万水千山走遍,目录也创建,接下来就是保存图片。又用到文件操作相关知识,千万注意,要想将图片成功保存至上面创建的目录,必需指定绝对路径,所以设置self.path是为了方便此处调用。


6、集合各操作并获取多页。两个循环,一个是多页,一个是多个图片的保存。关键在格式化每一页索引链接。

观察可发现规律,网页URL格式为:'http://tieba.baidu.com/p'+帖子号+'?pn='+页数,所以可以设置:

self.siteURL = 'http://tieba.baidu.com/p/' + str(Num)self.url=self.siteURL+'?pn='+str(page)


三、奉上源码

#usr/bin/env python# -*- coding: utf-8 -*-__author__='WYY'__date__='2017.03.14'#实战小项目:百度贴吧爬虫import urllib2import requestsimport reimport osimport timeimport randomfrom bs4 import BeautifulSoup#定义一个Tool()类方便清洗数据class Tool():    removeImg = re.compile('<img.*?>|{7}| ') # 去除img标签,1-7位空格,     removeAddr = re.compile('<a.*?>|</a>') # 删除超链接标签    replaceLine = re.compile('<tr>|<div>|</div>|</p>') # 把换行的标签换位\n    replaceTD = re.compile('<td>') # 把表格制表<td>换为\t    replaceBR = re.compile('<br><br>|<br>|</br>|</br></br>') # 把换行符或者双换行符换为\n    removeExtraTag = re.compile('.*?') # 把其余标签剔除    removeNoneLine = re.compile('\n+') # 把多余空行删除    def replace(self, x):        x = re.sub(self.removeImg, "", x)        x = re.sub(self.removeAddr, "", x)        x = re.sub(self.replaceLine, "\n", x)        x = re.sub(self.replaceTD, "\t", x)        x = re.sub(self.replaceBR, "\n", x)        x = re.sub(self.removeExtraTag, "", x)        x = re.sub(self.removeNoneLine, "\n", x)        return x.strip() # 把strip()前后多余内容删除#定义一个Spider类class Spider():    #初始化参数    def __init__(self):        self.tool = Tool()    #获取源码    def getSource(self,url):        user_agents=['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0','Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533+ \(KHTML, like Gecko) Element Browser 5.0','IBM WebExplorer /v0.94', 'Galaxy/1.0 [en] (Mac OS X 10.5.6; U; en)','Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)','Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14','Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) \Version/6.0 Mobile/10A5355d Safari/8536.25','Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) \Chrome/28.0.1468.0 Safari/537.36','Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; TheWorld)']        # user_agent在一堆范围中随机获取        # random.randint()获取随机数,防止网站认出是爬虫而访问受限        index=random.randint(0,9)        user_agent=user_agents[index]        headers = {'User_agent': user_agent}        html=requests.get(url,headers=headers)        return html.text    #获取帖子标题    def getTitle(self,url):        result=self.getSource(url)        pattern=re.compile('<h1.*?title.*?>(.*?)</h1>',re.S)        items=re.search(pattern,result)        print u'这篇帖子标题为:',self.tool.replace(items.group(1))    #获取帖子总页数    def getPageNumber(self,url):        result=self.getSource(url)        pattern=re.compile('<ul.*?l_posts_num.*?<span class="red">(.*?)</span>',re.S)        items=re.search(pattern,result).group(1)        print u'帖子共有',items,u'页'        return items    #获取评论内容    def getContent(self,url):        result = self.getSource(url)        pattern=re.compile('<a data-field.*?p_author_name.*?">(.*?)</a>.*?<div id="post_content_.*?>(.*?)</div>',re.S)        items=re.findall(pattern,result)        #获取楼层数可以直接用循环,省去正则匹配的麻烦        number = 1        for item in items:            #item[0]为楼主,item[1]为发言内容,使用\n换行符打出内容更干净利落            #item[1]中可能有img链接,用自定义Tool工具清洗            print u'\n', number, u'楼', u'\n楼主:', item[0], u'\n内容:', self.tool.replace(item[1])            time.sleep(0.01)            number += 1    #获取晒图,清洗获得链接并保存入list    def getImage(self,url):        result=self.getSource(url)        soup=BeautifulSoup(result,'lxml')        #此处用BeautifulSoup显然更高效        #find_all()返回一个list,find()返回一个元素        #注意class属性和python内置的重合,所以加_变成class_        items=soup.find_all('img',class_="BDE_Image")        images=[]        number=0        for item in items:            print u'发现一张图,链接为:',item['src']            images.append(item['src'])            number+=1        if number>=1:            print u'\n',u'共晒图',number,u'张,厉害了我的哥!!!'        else:            print u'喏,没有图......'        return images    #创建目录    def makeDir(self,path):        self.path=path.strip()        E=os.path.exists(os.path.join('F:\Desktop\code\LvXing', self.path))        if not E:            #创建新目录,若想将内容保存至别的路径(非系统默认),需要更环境变量            #更改环境变量用os.chdir()            os.makedirs(os.path.join('F:\Desktop\code\LvXing', self.path))            os.chdir(os.path.join('F:\Desktop\code\LvXing', self.path))            print u'正在创建名为',self.path,u'的文件夹'            return self.path        else:            print u'名为',self.path,u'的文件夹已经存在...'            return False    #万水千山走遍,接下来就是保存美图    def saveImage(self,detailURL,name):        data=urllib2.urlopen(detailURL).read()        fileName=name+'.'+'jpg'        #保存文件,一定要用绝对路径      `        #所以设置self.path,是为了方便后面函数无障碍调用        f=open(r'F:\Desktop\code\LvXing\%s\%s'%(self.path,fileName),'wb')        f.write(data)        f.close()        print u'成功保存图片',fileName    #集合所有的操作,并获取多页    def getAllPage(self,Num):        self.siteURL = 'http://tieba.baidu.com/p/' + str(Num)        #获取帖子标题        self.getTitle(self.siteURL)        #获取帖子页数        numbers=self.getPageNumber(self.siteURL)        for page in range(1,int(numbers)+1):            #格式化索引链接            self.url=self.siteURL+'?pn='+str(page)            print u'\n\n',u'正准备获取第',page,u'页的内容...'            #获取评论            print u'\n',u'正准备获取评论...'            self.getContent(self.url)            #每一页创建一个文件            self.makeDir(path='page'+str(page))            #获取图片            print u'\n',u'正准备获取图片...'            images=self.getImage(self.url)            print u'\n',u'正准备保存图片...'            number=1            #保存图片,先从之前的list中找链接            for detailURL in images:                name='page'+str(page)+'num'+str(number)                self.saveImage(detailURL,name)                time.sleep(0.1)                number+=1            print u'\n\n',u'完成第',page,u'页'        print u'\n\n',u'恭喜,圆满成功!'#raw_input()实现和外部交互,想看哪个贴就看哪个贴Num=int(raw_input('老哥儿/老妹儿,输入帖子号呗:'))spider=Spider()spider.getAllPage(Num)


四、结果

来看最后的结果

输入帖子号获取一些列信息

打印评论

(我好像发现了什么。。。微笑

打印链接

保存图片

最后一页

来看看文件发生了什么变化。

图片已经全部保存到指定文件夹啦~



五、题外(可不看)

爬完上面这个贴,又去胡乱搜寻,发现两有趣的贴。

一个是:国外朋友的世界一周旅行记1,Uca姐的摄影好美(献给所有爱旅者)

另一个:背起画夹去旅行——且行且绘(陆续更新)

1)、前面这一个介绍了一个日本旅行摄影师的世界一周旅行记的故事,照片色彩明丽、利落干净,迎面满是异域风情。

举例几个图:


 




 

一共100页,一页也就四五十张图。。。闭嘴

 



2)另一个帖子更是好玩,楼主非常有才,把沿途所见所闻都一一画下,画风那叫一个清新雅致,不得不献上膝盖。

放几个图感受一下:






觉得楼主应该给我广告费微笑

本文升级成一个文艺技术帖。。。

好啦就是这样啦~


2 0
原创粉丝点击