一起学爬虫——使用Beautiful Soup爬取网页
要想学好爬虫,必须把基础打扎实,之前发布了两篇文章,分别是使用XPATH和requests爬取网页,今天的文章是学习Beautiful Soup并通过一个例子来实现如何使用Beautiful Soup爬取网页。
什么是Beautiful Soup
- Beautiful Soup是一款高效的Python网页解析分析工具,可以用于解析HTL和XML文件并从中提取数据。
- Beautiful Soup输入文件的默认编码是Unicode,输出文件的编码是UTF-8。
- Beautiful Soup具有将输入文件自动补全的功能,如果输入的HTML文件的title标签没有闭合,则在输出的文件中会自动补全,并且还可以将格式混乱的输入文件按照标准的缩进格式输出。
Beautiful Soup要和其他的解析器搭配使用,例如Python标准库中的HTML解析器和其他第三方的lxml解析器,由于lxml解析器速度快、容错能力强,因此一般和Beautiful Soup搭配使用。
初始化Beautiful Soup对象的代码:
html =
'''
<html><title>Hello Beautiful Soup</title><p>Hello</p></html>
'''
soup = BeautifulSoup(html,'lxml')
只需把第二个参数写成"lxml"即可使用lxml解析器初始化Beautiful Soup对象。
Beautiful Soup提供了三种选择器用去爬取节点中的数据,分别是节点选择器、方法选择器和CSS选择器。下面分别介绍着三个选择器的用法。
节点选择器:
HTML网页有title、p、a、head、tr、td等节点。通过Beautiful Soup对象+"."+节点即可直接访问到节点。
Beautiful Soup对象+"."+节点+"."+string即可提取到节点的文本信息。
用法 | 描述 |
---|---|
soup.title | 选择第一个title节点 |
soup.title.string | 提取第一个title节点的文本信息 |
soup.title.attrs | 获取第一个title节点的所有属性,返回的结果的词典。 如果有class属性,则class属性返回的是list,class属性之间以空格当做分隔符 |
soup.p.contents | 获取第一个p节点的所有直接子节点。 该方法返回的是第一个p节点中包含的所有直接子字节点和文本, 不包含孙节点,两个节点之间的文本也当做是一个节点返回。 返回的结果是列表 |
soup.p.children | 返回第一个p节点的所有直接子节点,返回的结果是list_iterator对象 |
soup.p.descendants | 获取第一个p节点的所有子孙节点 |
soup.a.parent | 获取第一个a节点的父节点 |
soup.a.parents | 获取第一个a节点的所有祖先节点 |
soup.p.next_siblings | 获取第一个p节点的下一个兄弟节点 |
soup.p.previous_siblings | 获取第一个p节点的上一个兄弟节点 |
方法选择器:
根据传入的参数查找符合条件的节点。
下面是方法选择器提供的方法:
方法 | 描述 |
---|---|
find_all(name,attrs,recursive,text,**kwargs) | 根据传入参数查找所有符合条件的节点, name是节点名,attrs属性值,text文本内容等。 text参数可以是字符串,也可以是正则表达式: soup.find_all(text=re.compile('test')) |
find(name,attrs,recursive,text,**kwargs) | 返回第一个符合条件的节点 |
find_parents() | 返回所有祖先节点 |
find_parent() | 返回父节点 |
find_next_siblings() | 往后查找,所有兄弟节点 |
find_next_sibling() | 往后查找,返回第一个兄弟节点 |
find_previous_siblings() | 往前查找,返回所有兄弟节点 |
find_previous_sibling() | 往前查找,返回第一个兄弟节点 |
在使用上面的方法时,如果参数中有Python的关键字,则需要在参数下面加一个下划线,例如下面的代码,class是Python的关键字,必须在class后加下划线class_="title_class":
from bs4 import BeautifulSoup
html = '''
<html>
<body>
<title id="title_id" class="title_class" name="title name">Test BeautifulSoup</title>
<p>
<a href = "./test_beautifulsoup.html">test beautifulsoup link<a>
</p>
<ul>
<li class="animal">cat</li>
<li class="animal">dog</li>
</ul>
</body>
</html>
'''
soup = BeautifulSoup(html,'lxml')
print(soup.find_all(name='title',class_='title_class'))
CSS选择器:
BeautifulSoup还支持获取css元素,例如ul、div、li等元素。CSS选择器主要提供select()方法获取符合条件的节点(Tag对象),然后通过节点的get_text()方法和text属性可以获取该节点的文本值。
select方法还可以根据css的样式规则选择相应的节点:
from bs4 import BeautifulSoup
html = '''
<html>
<body>
<title id="title_id" class="title_class" name="title name">Test BeautifulSoup</title>
<p>
<a href = "./test_beautifulsoup.html">test beautifulsoup link<a>
</p>
<ul class="animal" id="aninal_id">
<li class="cat">cat</li>
<li class="animal dog">dog</li>
</ul>
<ul class="fruit" id = "fruit_id">
<li class="apple">apple</li>
<li class="banana">banana</li>
</ul>
</body>
</html>
'''
soup = BeautifulSoup(html,'lxml')
print('获取id为title_的所有节点')
print(soup.select('#title_id'))
print('获取class为title_的所有节点')
print(soup.select('.title_class'))
print('获取所有ul节点下面的所有li节点')
print(soup.select('ul li'))
print('获取所有class为fruit节点下的所有li节点')
print(soup.select('.fruit li'))
print('获取所有class为fruit节点下的第一个li节点的文本值')
print(soup.select('.fruit li')[0].string)
print('获取所有class为fruit节点下的第一个li节点的文本值')
print(soup.select('.fruit li')[0].get_text())
print('获取所有class为fruit节点下的第一个li节点的class属性值,注意class属性返回的是list列表,属性之间用空格分隔')
print(soup.select('.fruit li')[0].attrs['class'])
print(soup.select('.animal li')[1].attrs['class'])
print('循环迭代所有ul下面的所有li节点的文本值')
for li in soup.select('ul li'):
print(li.text)
下面使用Beautiful Soup爬取豆瓣音乐排行榜。
在浏览器中打开豆瓣音乐排行榜,打开浏览器,输入网址:https://music.douban.com/chart,我们要抓取的是每首歌曲的排名、歌曲名、演唱者、播放次数、上榜天数等数据。
下面分析怎么通过beautiful soup抓取到我们的数据。
通过开发者工具,我们可以看到所有歌曲是在class为article的div中,然后每首个在class为clearfix的li中。
因此首先使用css选择器获取到class为article下面的所有li节点:
soup.select(".article li")
然后查看每首歌曲的html代码:
红色框部分是一首歌的html代码。
歌曲排名在class为“gree-num-box”的span节点中,因为span节点是<li class="clearfix">
节点的子节点,获取排名的代码为:li.span.text
绿色框中A节点中是歌曲的链接和图片链接,获取歌曲链接的代码为:li.a['href']
蓝色框中是歌曲的名字、演唱者和播放次数,歌曲名是在class="icon-play"的H3节点中,因此可以使用方法选择器中的find()方法获取到H3节点,然后获取H3节点下面a节点中的文本信息就是歌曲的名字,代码为:li.find(class_="icon-play").a.text
获取演唱者和播放次数的代码为:
li.find(class_="intro").p.text.strip()
获取上榜天数的代码为:
li.find(class_="days").text.strip()
在豆瓣音乐排行榜的页面一个现实20首歌曲,前面10首歌曲会有图片,后面10首歌曲是没有图片的,因此后面10首歌曲将不获取图片的地址。
另外还有一点需要注意的是,后面10首歌曲的演唱者和播放次数是在class="icon-play"的p节点中:
而该节点中有a节点,要想获取a节点外的信息,必须使用节点选择器的contents方法:
li.find(class_="intro").p.contents[2].strip()
contents返回的是p节点的直接子节点,以列表的形式返回,这里返回列表中有3个元素,分别是
后的字符串,a节点、演唱者/播次数。contents会将直接子节点之间的换行符也当做一个元素。
代码整理后如下:
# coding:utf-8
from bs4 import BeautifulSoup
import requests
def parseHtml(url):
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}
response = requests.get(url,headers=headers)
soup = BeautifulSoup(response.text,'lxml')
#使用css选择器获取class="article"的节点下面的所有li节点
for index,li in enumerate(soup.select(".article li")):
if(index <10):
print('歌曲排名:' + li.span.text)
print('歌曲链接:' + li.a['href'])
print('歌曲名:' + li.find(class_="icon-play").a.text)#使用方法选择器
print('演唱者/播放次数:' + li.find(class_="intro").p.text.strip())
print('上榜时间:'+li.find(class_="days").text.strip())
else:
print('歌曲排名:' + li.span.text)
print('歌曲名:' + li.find(class_="icon-play").a.text)
print('演唱者/播放次数:' + li.find(class_="intro").p.contents[2].strip())#方法选择器和节点选择器搭配使用
print('上榜时间:' + li.find(class_="days").text.strip())
print('—————————————————强力分隔符———————————————————')
def main():
url = "https://music.douban.com/chart"
parseHtml(url)
if __name__ == '__main__':
main()
本文通过爬取豆瓣音乐排行榜的小项目学习了如何使用Beautiful Soup的节点选择器、方法选择器、CSS选择器来爬取一个网页。这三个选择器可以混合搭配使用。
一起学爬虫——使用Beautiful Soup爬取网页的更多相关文章
- 使用Beautiful Soup爬取猫眼TOP100的电影信息
使用Beautiful Soup爬取猫眼TOP100的电影信息,将排名.图片.电影名称.演员.时间.评分等信息,提取的结果以文件形式保存下来. import time import json impo ...
- 一起学爬虫——使用xpath库爬取猫眼电影国内票房榜
之前分享了一篇使用requests库爬取豆瓣电影250的文章,今天继续分享使用xpath爬取猫眼电影热播口碑榜 XPATH语法 XPATH(XML Path Language)是一门用于从XML文件中 ...
- 爬虫-----selenium模块自动爬取网页资源
selenium介绍与使用 1 selenium介绍 什么是selenium?selenium是Python的一个第三方库,对外提供的接口可以操作浏览器,然后让浏览器完成自动化的操作. sel ...
- [Python爬虫] 使用 Beautiful Soup 4 快速爬取所需的网页信息
[Python爬虫] 使用 Beautiful Soup 4 快速爬取所需的网页信息 2018-07-21 23:53:02 larger5 阅读数 4123更多 分类专栏: 网络爬虫 版权声明: ...
- python爬虫之Beautiful Soup基础知识+实例
python爬虫之Beautiful Soup基础知识 Beautiful Soup是一个可以从HTML或XML文件中提取数据的python库.它能通过你喜欢的转换器实现惯用的文档导航,查找,修改文档 ...
- python爬虫学习(二):定向爬虫例子-->使用BeautifulSoup爬取"软科中国最好大学排名-生源质量排名2018",并把结果写进txt文件
在正式爬取之前,先做一个试验,看一下爬取的数据对象的类型是如何转换为列表的: 写一个html文档: x.html<html><head><title>This is ...
- python3爬虫爬取网页思路及常见问题(原创)
学习爬虫有一段时间了,对遇到的一些问题进行一下总结. 爬虫流程可大致分为:请求网页(request),获取响应(response),解析(parse),保存(save). 下面分别说下这几个过程中可以 ...
- 【python网络编程】新浪爬虫:关键词搜索爬取微博数据
上学期参加了一个大数据比赛,需要抓取大量数据,于是我从新浪微博下手,本来准备使用新浪的API的,无奈新浪并没有开放关键字搜索的API,所以只能用爬虫来获取了.幸运的是,新浪提供了一个高级搜索功能,为我 ...
- 【图文详解】scrapy爬虫与动态页面——爬取拉勾网职位信息(2)
上次挖了一个坑,今天终于填上了,还记得之前我们做的拉勾爬虫吗?那时我们实现了一页的爬取,今天让我们再接再厉,实现多页爬取,顺便实现职位和公司的关键词搜索功能. 之前的内容就不再介绍了,不熟悉的请一定要 ...
随机推荐
- dijstra算法
无向图.赋权有向图 的最短路径
- 【C/C++】Dijkstra算法的简洁实现
Dijkstra的实现有很多种,下面给出一种较为简洁和高效的实现,可以作为模板快速使用. 1. 使用邻接表存储图: 2. 使用标准STL的vector存储每个点的所有邻接边: 3. 使用pair记录当 ...
- 欧拉筛法模板and 洛谷 P3383 【模板】线性筛素数(包括清北的一些方法)
题目描述 如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内) 输入格式 第一行包含两个正整数N.M,分别表示查询的范围和查询的个数. 接下来M行每行包含一个不小于1 ...
- Forget Guava: 5 Google Libraries Java Developers Should Know
Forget Guava: 5 Google Libraries Java Developers Should Know Published on 2016 7 13 Somenath PandaFo ...
- fzyzojP1635 -- 平均值
做法大概有两种: 1.二分平均值,每个值减去平均值,求有没有一个区间的总和大于等于0 (类比,中位数是二分之后,比mid大的为1,小的为0,看有没有区间大于等于0这样) 最值问题——判定问题 单调队列 ...
- DirectX11 With Windows SDK--11 混合状态与光栅化状态
前言 虽然这一部分的内容主要偏向于混合(Blending),但这里还需提及一下,关于渲染管线可以绑定的状态主要有如下四种: 光栅化状态(光栅化阶段) 采样器状态(像素着色阶段) 混合状态(输出合并阶段 ...
- ACM-ICPC 2018 沈阳赛区网络预赛 K Supreme Number(规律)
https://nanti.jisuanke.com/t/31452 题意 给出一个n (2 ≤ N ≤ 10100 ),找到最接近且小于n的一个数,这个数需要满足每位上的数字构成的集合的每个非空子集 ...
- Iterate over slices of a string
def iter_slices(string, slice_length): """Iterate over slices of a string."" ...
- IDEA 代码规范插件
前言 在工作过程中,每个人的代码习惯都不同,在一起工作做同一个项目,如果按照自己的习惯来,有可能造成代码维护困难,开发进度缓慢等. 代码规范的重要性 谷歌发布的代码规范中指出,80% 的缺失是由 20 ...
- 边缘检测之Canny
1. 写在前面 最近在做边缘检测方面的一些工作,在网络上也找了很多有用的资料,感谢那些积极分享知识的先辈们,自己在理解Canny边缘检测算法的过程中也走了一些弯路,在编程实现的过程中,也遇到了一个让我 ...