详解Python 采用 requests + Beautiful Soup 爬取房天下新楼盘推荐
最近一直在关注Python写爬虫相关的知识,尝试了采用requests + Beautiful Soup来爬取房天下(原搜房网)的推荐新楼盘。
不用不知道,一用发现有惊喜也有惊吓,本文就一同记录下惊喜和踩的一些乱码的坑。
首先,觉得Beautiful soup解析网页更加符合人类的常规思维,比使用正则表达式(python中的re库)更容易理解。 同时关于requests遇到了中文字符和特殊字符解码的问题。本文都将给于深入的解说。
软件环境
Python : 3.6.0
PyCharm: Community 2017.2
库1 : requests
库2 : beautifulsoup
Requests知识概要
Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。
完全支持Python3哦
1. 安装requests
可以采用pip安装requests,具体代码是:
pip install requests
2. 简单例子
下面例子中是几个常用的属性,response.text可以得到html的源代码,response.encoding默认为ISO-8859-1,此编码针对英文没有问题,如果我们的网页中带有中文,将会引起乱码的问题。后面有解决方案。
import requests response = requests.get("http://sh.fang.com/") #获取一个Http请求 print(response.encoding) #当前编码,默认为 ISO-8859-1 print(response.apparent_encoding) #当前网页的内容的实际编码 print(response.content) #content返回的是bytes型的原始数据 print(response.text) #text返回的是处理过的Unicode型的数据
Beautiful Soup简要知识
1. Beautiful Soup 是一个非常流行的 Python 模块。 该模块可以解析网页, 并
提供定位 内 容的便捷接 口 。 如果你还没有安装该模块, 可以使用下面的命令
安装其最新版本:
pip install beautifulsoup4
使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析为 soup 文档 。
2. 如何引用Beautiful Soup
from bs4 import BeautifulSoup
3. 一个简单例子
from bs4 import BeautifulSoup html = "<ul class='country'><li>中国</li><li>美国</li></ul>" # 解析html然后得到一个soup文档 soup = BeautifulSoup(html,'html.parser') html = soup.prettify() ul = soup.find('ul',attrs={'class':'country'}) #下面代码只返回一个匹配的元素 print(ul.find('li')) # returns the first match element #下面代码返回又有匹配的元素 for countryname in ul.find_all('li'): print(countryname)
实战爬取房天下推荐新楼盘
在Chrome中打开sh.fang.com地址,按F12观察新盘推荐tab的网页源代码结构
主要结构是: 顶层为一个名为ti011的div,下面有四个class为tenrtd的div用于四个楼盘的现实。每个楼盘下面有一个class = "text1"的div存储了楼盘名称,另一个class = "text2"的存储了楼盘的价格。
2. 第一版代码完成如下,但是发现有一个中文乱码的问题
from bs4 import BeautifulSoup import requests rep = requests.get("http://sh.fang.com/") html = rep.text soup = BeautifulSoup(html, 'html.parser') #获取顶层 新盘推荐 的整个div div = soup.find('div',attrs={'id':'ti011'}) #获取四个楼盘的div,更具他们的class = "tenrtd" for house in div.find_all('div', attrs={'class': 'tenrtd'}): # 根据class="text1"获取存储楼盘标题的div titleDiv = house.find('div', attrs={'class': 'text1'}) title = titleDiv.find('a').text # 根据class="text2"获取存储楼盘价格的div priceDiv = house.find('div', attrs={'class': 'text2'}) price = priceDiv.find('b').text print(title, " ", price)
输出的结果尽然是这样, Why?
Öнðº£ÌÄÍå 48000Ôª/©O »ªÒêÒÝÆ·À½Íå 43057Ôª/©O Öйú¹é¹È´´¿ÍSOHO ¼Û¸ñ´ý¶¨ ÐÂÎ÷ÌÁ¿×ȸ³Ç 14000Ôª/©O
3. 研究中文乱码问题
中文乱码也算是requests常见的一个问题,为什么会这样的呢,看bs自己的文档描述
Encodings When you receive a response, Requests makes a guess at the encoding to use for decoding the response when you access the Response.text attribute. Requests will first check for an encoding in the HTTP header, and if none is present, will use chardet to attempt to guess the encoding. The only time Requests will not do this is if no explicit charset is present in the HTTP headersand the Content-Type header contains text. In this situation, RFC 2616 specifies that the default charset must be ISO-8859-1. Requests follows the specification in this case. If you require a different encoding, you can manually set the Response.encoding property, or use the rawResponse.content.
其实重要的也就是如果没有在requests的header部分里面指定encoding的话,那么默认采用ISO-8859-1这个编码去解码response.content里面的字节数据。ISO-8859-1针对英文是没有问题的,但是针对中文就不行了。
解决思路当然就是换encoding,但是我们应该用什么编码呢?下面这个代码可以看到网页的实际encoding,下面代码将输出:GB2312 ,所以我们采用GB2312来解码我们的数据。
print(rep.apparent_encoding)
4.换编码解决中文字符
经过上面的研究,我们修订代码对response设定encoding = "GB2312"
rep.encoding = "GB2312"
运行后结果如下:
中金海棠湾 48000元/�O 华谊逸品澜湾 43057元/�O 中国归谷创客SOHO 价格待定 新西塘孔雀城 14000元/�O
发现代码显示的结果中㎡又乱码了,不应该啊,这又是为什么呢? 下面接着研究。。。
5. 研究解决特殊字符乱码问题
引起乱码的原因估计就是在字符集中找不到特定的字符,比如这个㎡。是不是GB2312这个字符集不够全面呢?带着这个疑问去查阅相关的资料关于中文的几个编码:
GB2312
GB 2312 或 GB 2312-80 是中国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,又称 GB 0,由中国国家标准总局发布,1981 年 5 月 1 日实施。GB 2312 编码通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持 GB 2312。GB 2312 标准共收录 6763 个汉字,其中一级汉字 3755 个,二级汉字 3008 个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的 682 个字符。GB 2312 的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75% 的使用频率。对于人名、古汉语等方面出现的罕用字,GB 2312 不能处理,这导致了后来 GBK 及 GB 18030 汉字字符集的出现。
GBK
GBK 即汉字内码扩展规范,K 为汉语拼音 Kuo Zhan(扩展)中“扩”字的声母。英文全称 Chinese Internal Code Specification。GBK 共收入 21886 个汉字和图形符号,包括:GB 2312 中的全部汉字、非汉字符号。BIG5 中的全部汉字。与 ISO 10646 相应的国家标准 GB 13000 中的其它 CJK 汉字,以上合计 20902 个汉字。其它汉字、部首、符号,共计 984 个。GBK 向下与 GB 2312 完全兼容,向上支持 ISO 10646 国际标准,在前者向后者过渡过程中起到的承上启下的作用。GBK 采用双字节表示,总体编码范围为 8140-FEFE 之间,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 XX7F 一条线
GB18030
GB 18030,全称:国家标准 GB 18030-2005《信息技术中文编码字符集》,是×××现时最新的内码字集,是 GB 18030-2000《信息技术信息交换用汉字编码字符集基本集的扩充》的修订版。GB 18030 与 GB 2312-1980 和 GBK 兼容,共收录汉字70244个。与 UTF-8 相同,采用多字节编码,每个字可以由 1 个、2 个或 4 个字节组成。编码空间庞大,最多可定义 161 万个字符。支持中国国内少数民族的文字,不需要动用造字区。汉字收录范围包含繁体汉字以及日韩汉字
从上文中可以简要的得出GB 2312 过时标准、GBK 微软标准、GB 18030 国家标准,字符个数方面:GB 18030 > GBK > GB2312
所以我们决定采用 GB18030来解码我们的数据,代码改动如下:
rep.encoding = "gb18030"
附上完整的代码
from bs4 import BeautifulSoup import requests rep = requests.get("http://sh.fang.com/") rep.encoding = "gb18030" html = rep.text soup = BeautifulSoup(html, 'html.parser') #获取顶层 新盘推荐 的整个div div = soup.find('div',attrs={'id':'ti011'}) #获取四个楼盘的div,更具他们的class = "tenrtd" for house in div.find_all('div', attrs={'class': 'tenrtd'}): # 根据class="text1"获取存储楼盘标题的div titleDiv = house.find('div', attrs={'class': 'text1'}) title = titleDiv.find('a').text # 根据class="text2"获取存储楼盘价格的div priceDiv = house.find('div', attrs={'class': 'text2'}) price = priceDiv.find('b').text print(title, " ", price)
输出结果:
中金海棠湾 48000元/㎡ 华谊逸品澜湾 43057元/㎡ 中国归谷创客SOHO 价格待定 新西塘孔雀城 14000元/㎡
问题解决了,关键知识点总结:
可以采用requests库来获取网页html
采用Beautiful soup基于html构建一个soup文档,然后用find 或者 find_all方法查询自己需要的html节点
根据目标网页的内容来更改response.encoding从而解决乱码问题

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
深入理解Python字符编码
不论你是有着多年经验的 Python 老司机还是刚入门 Python 不久,你一定遇到过UnicodeEncodeError、UnicodeDecodeError 错误,每当遇到错误我们就拿着 encode、decode 函数翻来覆去的转换,有时试着试着问题就解决了,有时候怎么试都没辙,只有借用 Google 大神帮忙,但似乎很少去关心问题的本质是什么,下次遇到类似的问题重蹈覆辙,那么你有没有想过一次性彻底把 Python 字符编码给搞懂呢? 完全理解字符编码 与 Python 的渊源前,我们有必要把一些基础概念弄清楚,虽然有些概念我们每天都在接触甚至在使用它,但并不一定真正理解它。比如:字节、字符、字符集、字符码、字符编码。 字节 字节(Byte)是计算机中数据存储的基本单元,一字节等于一个8位的比特,计算机中的所有数据,不论是保存在磁盘文件上的还是网络上传输的数据(文字、图片、视频、音频文件)都是由字节组成的。 字符 你正在阅读的这篇文章就是由很多个字符(Character)构成的,字符一个信息单位,它是各种文字和符号的统称,比如一个英文字母是一个字符,一个汉字是一个字符,一个标点...
- 下一篇
分布式文件系统FastDFS详解
上一篇文章《一次FastDFS并发问题的排查经历》介绍了一次生产排查并发问题的经历,可能有些人对FastDFS不是特别的了解,因此计划写几篇文章完整的介绍一下这个软件。 为什么要使用分布式文件系统呢? 嗯,这个问题问的好,使用了它对我们有哪些好处?带着这个问题我们来往下看: 单机时代 初创时期由于时间紧迫,在各种资源有限的情况下,通常就直接在项目目录下建立静态文件夹,用于用户存放项目中的文件资源。如果按不同类型再细分,可以在项目目录下再建立不同的子目录来区分。例如:resources\static\file、resources\static\img等。 优点:这样做比较便利,项目直接引用就行,实现起来也简单,无需任何复杂技术,保存数据库记录和访问起来也很方便。 缺点:如果只是后台系统的使用一般也不会有什么问题,但是作为一个前端网站使用的话就会存在弊端。一方面,文件和代码耦合在一起,文件越多存放越混乱;另一方面,如果流量比较大,静态文件访问会占据一定的资源,影响正常业务进行,不利于网站快速发展。 独立文件服务器 随着公司业务不断发展,将代码和文件放在同一服务器的弊端就会越来越明显。为了解...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Hadoop3单机部署,实现最简伪集群
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker快速安装Oracle11G,搭建oracle11g学习环境