上一节课我们学习了目前最方便的网络爬虫框架之一的 Ruquests 。事实上,仅仅使用Rquests 也无法让我们有效、方便的爬取指定的内容。Rquests 框架帮助我们很好封装了网页请求相关的功能,但是如何对爬取后的页面进行处理?如何对HTML进行解析?今天,我们就来了解一下BeautifulSoup------一款让你爬虫效率提高200%的第三方网页解析大杀器!
BeautifulSoup 简介
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.
我们注意到,官方说明中,提到了提取数据
这个词语。为什么已经爬取了网页源码,还要解析后才能提取到相关的内容呢?
我们先看一段我们上节课已经爬取过的网页代码:
html
......
<input type=hidden name=ch value=""><span class="btn_wr s_btn_wr bg" id=s_btn_wr><input type=submit value="百度一下" id=su class="btn self-btn bg s_btn"></span><span class=tools><span id=mHolder><div id=mCon><span>输入法</span></div><ul id=mMenu><li><a href="javascript:;" name=ime_hw>手写</a><li><a href="javascript:;" name=ime_py>拼音</a><li class=ln><li><a href="javascript:;" name=ime_cl>关闭</a></ul></span><span class=bd_bear_home></span></span></form> </div> </div> <div id=u><a class=toindex href=/>百度首页</a><span class=toindex></span>
......
现在有个问题摆在你的面前:如果不对网页进行解析,但是现在你想爬取手写
这个关键字,你该怎么做?
答案是:使用正则表达式。
我知道我们许多人之前听过正则表达式
这个概念,但是没有真正的使用过;或者是你之前已经学习过一段时间,但是痛苦的学习过程让你放弃了正则表达式
的深入学习...无论你之前是否知道这个词语,我都想告诉大家:正则表达式
在这门课中仅仅是一个课外自行学习的概念,并不会教你如何学习。
Anyway , 一句话:使用BeautifulSoup 让你能够更爽快的继续你的"网页爬虫"之路。让我们正式开始学习!
BeautifulSoup初体验
安装BeautifulSoup
学过之前课程的你,肯定对这个步骤已经很熟悉了。直接在控制台中输入:
bash
pip install BeautifulSoup4
需要指出的是,BeautifulSoup 只是封装了一些常用的功能,解析网页仍然需要一个解析器进行工作。BeautifulSoup官方文档中支持了以下几款解析器。
俗话说"天下武功,唯快不破",本课程就选择速度快的lxml
解析器!因此,正确安装BeautifulSoup后,我们还要安装一个第三方的解析库lxml
,方便我们更快的进行解析。
basic
pip install lxml
BeautifulSoup 快速开始
废话不多说,我们还是通过一个例子来进行详细的讲解:
python
from bs4 import BeautifulSoup
import requests
url = "http://gitbook.cn"
header = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
web_data = requests.get(url,header)
soup = BeautifulSoup(web_data.text,'lxml')
title = soup.title.string
urls = soup.find_all('a')
python
soup = BeautifulSoup(web_data.text,'lxml')
使用BeautifulSoup解析我们使用 Requests 爬取到的网页内容web_data.text
,并且使用lxml
解析器对其进行解析。
这句话基本上是我们使用BeautifulSoup 框架时最常用的一行代码。如果你实在是不了解其内在机制的话(说句实话,其实我对其也是不甚了解),那就直接拿来用------程序员的世界中,首先是运行到正确的结果,然后才是进一步了解整个步骤的内在机制。
通过这行代码,我们能够得到一个 BeautifulSoup
的对象 。接下来我们所有的网页获取都是操作这个对象来进行处理。BeautifulSoup 将复杂的HTML代码解析为了一个树形结构。每个节点都是可操作的Python 对象,常见的有四种:
- Tag
- NavigableString
- BeautifulSoup
- Comment
接下来我们对其进行一一介绍
Tag
(1)什么是Tag?简单的来说,Tag就是我们之前学过的HTML中的一个个标签!例如:
python
title = soup.title
上述代码是获取网站的标题。运行后得到的结果是
GitChat
让我们打开网页的源代码,查看一下是否正确
Bingo!我们可以直接通过soup.tag
获取对应的HTML中的标签信息!
(2)让我们看一下HTML网页中的一个比较特别的Tag
html
<meta name="description" content="GitChat 是一款基于微信平台的知识分享产品。通过这款产品我们希望改变IT知识的学习方式。">
<meta name="keywords" content="GitChat,机器学习,大数据,程序员,用户体验,软件开发,知识付费,技术分享">
一般来说,description
和keywords
是一个网页的关键信息之一。具体的,如果你只是想获取这个网页的大概内容,那么我们可以直接获取这两个标签中的信息就可以了。我们可以这样写:
python
description = soup.find(attrs={"name": "description"})
keywords = soup.find(attrs={"name": "keywords"})
NavigableString
既然能够获取到标签,那么如果获取标签的内容呢?很简单,直接在后面加上.string
就可以了!
python
title = soup.title.string
print(title) # 输出 Gitboot
description = soup.find(attrs={"name": "description"})['content']
keywords = soup.find(attrs={"name": "keywords"})['content']
BeautifulSoup
BeautifulSoup
对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag
对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.
Comment
Comment
对象是一个特殊类型的 NavigableString
对象,但是但是当它出现在HTML文档中时, 如果不对Comment
对象进行处理,那么我们在后续的处理中可能会出现问题。具体的解决方案,可以参考:关于BeautifulSoup的总结
BeautifulSoup 实战
上面涉及到了太多的理论知识,实在是"太过枯燥"。让我们在实战中学习BeautifulSoup 吧!
我们今天爬取的网站是GitChat 达人课,这是大家用来学习的网站。
(1)基础操作
python
from bs4 import BeautifulSoup
import requests
url = "http://gitbook.cn/gitchat/news"
header = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng, */*;q=0.8','Accept-Language': 'zh-CN,zh;q=0.9','User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
web_data = requests.get(url,header)
soup = BeautifulSoup(web_data.text,'lxml')
title = soup.title.string
运行上述代码后,我们直接print(title)
,会显示网站的标题"三石·道 ------ 三石的生活感悟和技术博客"
(2)用select()
函数定位指定的信息
如上图所示,我们想要爬取右上角的"前端专题",该怎么操作呢?
python
theme = soup.select('#indexRight > div:nth-of-type(3) > a:nth-of-type(1) > span')[0].get_text()
在
Tag
或BeautifulSoup
对象的.select()
方法中传入字符串参数,即可使用CSS选择器的语法找到tag
使用.select()
方法可以帮我们定位到指定的tag。那么,我们该如何确定这个指定的位置呢?让我们看一下Gif图片吧!
具体的,我们首先将鼠标放在所要定位的文字上,接下来,进行如下操作:
- 右击鼠标,选择
检查
- 在弹出的检测台中,选定对应的文字
- 右击鼠标,选择"copy"
- 选择"copy selector"
让我们看一下我们复制后的内容
#indexRight > div:nth-child(3) > a:nth-child(1) > span
我们将child
修改为of-type
就能够得到最后正确的线性路径。
如果只想得到tag中包含的文本内容,那么可以用
get_text()
方法,这个方法获取到tag中包含的所有文版内容包括子孙tag中的内容。
(3)使用.get()
获取指定属性
假设HTML中有如下的代码
html
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
我们如何获取到里面的文字呢?没错,直接使用.get_text()
函数就可以了。
那么,如果我们只想获取它的url地址呢?或者它所对应的 class 名字呢?这就需要我们使用.get()
函数
class_name = soup.select("path")[0].get("class")
url_address = soup.select("path")[0].get("href")
课后总结
本节课粗略的对BeautifulSoup 进行了讲解。里面涉及到大量的原理,和之前的文章相比,较为枯燥。如果你不愿意学习全部的内容,同时,为了方便接下来的实战课程,我希望你可以重点关注以下几个我们以后要经常用到的知识点:
- 如何获取网页信息在HTML中对应的位置,如何使用Chrome 浏览器获取到对应的selector
.get_text()
函数的使用.get()
函数的使用- 一定一定要浏览BeautifulSoup的官方文档,它是提供中文文档的!