首页 > 代码库 > python爬虫实例详细介绍之爬取大众点评的数据

python爬虫实例详细介绍之爬取大众点评的数据

python 爬虫实例详细介绍之爬取大众点评的数据



一.

Python作为一种语法简洁、面向对象的解释性语言,其便捷性、容易上手性受到众多程序员的青睐,基于python的包也越来越多,使得python能够帮助我们实现越来越多的功能。本文主要介绍如何利用python进行网站数据的抓取工作。我看到过利用c++和Java进行爬虫的代码,c++的代码很复杂,而且可读性、可理解性较低,不易上手,一般是那些高手用来写着玩加深对c++的理解的,这条路目前对我们不通。Java的可读性还可以,就是代码冗余比较多,同样的一个爬虫,java的代码量可能是python的两倍,感觉也没有python容易上手。因此,建议大家以后如果对爬虫有兴趣的话直接使用python就好。

二.本文首先爬取大众点评-北京的火锅这个条目下的部分数据。下面,我主要针对如何爬取数据进行讲解,针对数据进行分析的部分就略过。会根据我自己的理解和经验对代码进行详细的分析,比较适合初学者,高手请出门右转。由于是针对初学者,所以我最大程度地将代码进行精简,当然也因此删去了一些功能。

三、注意!

不要盲目的直接把代码复制直接运行,最好先看完本文,然后再运行。因为我是在ubuntu14.04下运行的我的代码,因此在获取数据时的编码格式不一样,输出信息到窗口时的编码也会有所不同,在Linux下默认编码是utf-8,而在windows下默认编码是gbk,所以,如果系统不同,直接运行代码,可能会输出乱码,这不代表我的代码有问题。需要注意的问题,在本文中我基本上都给了讲解,如果还有问题的话,欢迎留言探讨。

本人的浏览器为forefox,不同浏览器的查看元素的方法和界面也会有所不同,我在下文进行介绍时,只能以我的浏览器为准,不同的浏览器可以自己找一下相应的东西,一般不会差太多。

四.闲话少叙,直接上代码。

[python] view plain copy

  1. # -*- coding:utf-8 -*-  

  2. import re  

  3. from bs4 import BeautifulSoup  

  4. import json  

  5. import threading  

  6. from requests import Session  

  7. class dazp_bj:  

  8.     def __init__(self,category):  

  9.         self.baseUrl=‘http://www.dianping.com‘  

  10.         self.bgurl=category[0]  

  11.         self.typename=category[1]  

  12.         self.page=1  

  13.         self.pagenum=10 #设置最大页面数目,大众点评每个条目下最多有50页,可以根据自己需求进行设置  

  14.         self.headers={  

  15.             "Host":"www.dianping.com",  

  16.             "User-Agent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:48.0) Gecko/20100101 Firefox/48.0",  

  17.             #此User-Agent是我本人的参数,在使用时记得修改为自己的参数,如何获取下四.4部分有讲解  

  18.             "Referer":"http://www.dianping.com/beijing",  

  19.         }  

  20.     def start(self):  

  21.         self.s=Session()    #定义一个Session()对象  

  22.         print self.bgurl,self.typename  

  23.         print "please wait for 15"  

  24.         dazp_bj.__parseHtml(self,self.bgurl) #调用__parseHtml函数  

  25.         print ‘getdata down‘  

  26.     def __parseHtml(self,preurl):  

  27.         _json=dict()    #定义一个字典用以存储数  

  28.         html=self.s.post(preurl,headers=self.headers).text  #发送请求,获取html  

  29.         soup=BeautifulSoup(html,‘lxml‘#进行解析  

  30.                 name=[‘商家名称‘,‘评论数量‘,‘人均消费‘,‘地址‘,‘评分‘,‘链接‘]  

  31.         for li in soup.find(‘div‘,class_="shop-wrap").find(‘div‘,id="shop-all-list").ul.find_all(‘li‘):  

  32.             info=li.find(‘div‘,class_=‘txt‘)  

  33.             _json[name[0]]=info.find(‘div‘,class_=‘tit‘).a.h4.get_text().encode(‘utf-8‘)                      

  34.             _json[name[1]]=int(info.find(‘div‘,class_=‘comment‘).find(‘a‘,class_="review-num").b.get_text().encode(‘utf-8‘))  

  35.             _json[name[2]]=int(re.sub(‘¥‘,‘‘,info.find(‘div‘,class_=‘comment‘).find(‘a‘,class_="mean-price").b.get_text().encode(‘utf-8‘)))  

  36.             _json[name[3]]=info.find(‘div‘,class_=‘tag-addr‘).find(‘span‘,class_=‘tag‘).get_text().encode(‘utf-8‘)+info.find(‘div‘,class_=‘tag-addr‘).find(‘span‘,class_=‘addr‘).get_text().encode(‘utf-8‘)  

  37.             _json[name[4]]=float(info.find(‘span‘,class_=‘comment-list‘).find_all(‘b‘)[0].get_text())+float(info.find(‘span‘,class_=‘comment-list‘).find_all(‘b‘)[1].get_text())+float(info.find(‘span‘,class_=‘comment-list‘).find_all(‘b‘)[2].get_text())  

  38.             _json[name[5]]=self.baseUrl+info.find(‘div‘,class_=‘tit‘).a[‘href‘]               

  39.             with open(self.typename+‘.json‘,‘a‘) as outfile:  

  40.                 json.dump(_json,outfile,ensure_ascii=False)  

  41.             with open(self.typename+‘.json‘,‘a‘) as outfile:  

  42.                 outfile.write(‘,\n‘)      

  43.         self.page+=1  

  44.         if self.page<=self.pagenum:  

  45.             self.nexturl=self.baseUrl+soup.find(‘div‘,class_=‘page‘).find(‘a‘,class_=‘next‘)[‘href‘]  #获得下一页的链接  

  46.             dazp_bj.__parseHtml(self,self.nexturl)        

  47. if __name__==‘__main__‘:  

  48.     cat=[(r‘http://www.dianping.com/search/category/2/10/g110‘,u‘火锅 ‘)]  

  49.     obj=list()  

  50.     obj.append(dazp_bj(cat[0]))  

  51.     [threading.Thread(target=foo.start(),args=()).start for foo in obj]#多线程执行obj列表中的任务  


五.上面是所有代码。接下来则对代码进行精细的讲解。

1.# -*- coding:utf-8 -*- #这句代码是在文件的开头设置好编码的格式,这样就能够在文件里写中文,否则python2.7会默认使用ASCII编码。个人建议最好在所有的.py文件的开头都写上这句代码,防止不必要的错误。有时候这样设置后在爬取某些网站时仍然会出现问题,比如说会报这样的错误:UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 0-1: ordinal not in range(128) 。这种情况下可以加如下几行代码:

[python] view plain copy

  1. import sys  

  2. reload(sys)  

  3. sys.setdefaultencoding("utf-8" )  

暂时不知道为什么会这样,但是这样就可以解决问题了。据说python2.7在这方面特别容易出错,在python3中则会好很多,可能以后会转到python3吧,差别应该不大,新手可以直接学3.

2.现在讲一下引用的包。re是正则表达式,对网页进行解析时很有用,非常强大,当你掌握了正则表达式的使用后,你就可以在各个网页中来回驰骋了;json是一种数据格式,我利用json文件在保存爬取到的字典数据,感觉json保存字典数据很强大,调用读取都很便捷。之前看到一个txt文件保存的字典数据,在读数据的时候很麻烦,没有json便捷;threading 是多线程,可以提高爬取效率,本文中因为只抓了一个链接,因此没有用到它的功能,在cat中多加入几个链接,并append到obj中就可以使用这个功能;bs4是python的一个很强大的对网页进行解析的包,如果没有这个包,如果要解析数据都是要使用正则表达式的,那个场面一定很惨烈。python也提供了另一种方式方便查找网页中的标签:xpath,只用过一次,配合firefox的firebug很好用,在定位到感兴趣的标签后直接右键即可获得该标签的xpath路径,省得我们还要一个一个标签去找,但是当我们爬取的网站比较大、复杂的时候,这种方式可能就不是那么适用了,因为不同条目的同一种类的数据可能在不同的位置,或者有些数据没有值的情况下这个标签就不存在,这个时候只能使用beautifulsoup来根据id、class、name等值准确定位到标签;requests是向服务器发送请求的包,有post和get两张方法,可以传入很多参数,如headers,cookies,data,params等,headers是你浏览器的请求头数据,传入这个参数可以将你的爬取访问伪装成浏览器的正常访问,对一些网站有效,有些网站则需要传入cookies,data和params是在其他情况下需要传入的参数,初学者一般用不到,在此就不赘述,需要的时候百度基本上可以找到方法。requests下的Session()方法和request有点相似,也包括get和post方法,传的参数也基本上差不多,但是会话对象requests.Session能够跨请求地保持某些参数,比如cookies,即在同一个Session实例发出的所有请求都保持同一个cookies,而requests模块每次会自动处理cookies,这样就很方便地处理登录时的cookies问题。但是本文中貌似不需要使用session,只是习惯性的使用这个,大家可以修改后试一下:将后文的self.s替换为requests .

3.首先定义了一个类,类下面有很多方法。__init__是对类的参数进行初始化,类内的全局变量都可以在此设置,在其他地方设置也可,不过要在变量名前加上global。start(),类中的方法和函数都在此进行调用,start可以说是类的入口。__parseHtml是定义的爬取数据的主函数。

4.下面介绍如何针对每个数据条目定制解析语句,以及如何获得headers参数。

技术分享

打开页面之后右键然后选择查看元素(有些浏览器是检查元素,我使用的是firefox,注意不是查看源代码)然后点网络(Network),然后点左上角“所有”旁边的删除符号,然后点击重新载入(或者刷新页面),可以看到下图所示的情况:

技术分享

点击最上面的那一条,得到下图,请求头信息、cookie、参数等信息都在这里。上面代码中的headers内的User-Agent是我的浏览器信息,在使用时需要根据自己的电脑进行修改。请求头中有些数据是不需要的,因此我只选择了几条。

技术分享


本文出自 “李世龙” 博客,谢绝转载!

python爬虫实例详细介绍之爬取大众点评的数据