首页 » 产品日记 » 正文

python模块BeautifulSoup

在通过requests获取到目标数据之后,并不是所有的内容都是我们需要的,所以需要用到一些方法把我们不需要的给剔除掉,或者说把我们想要的单独摘出来,这个时候BeautifulSoup就出现了。

这里有必要提一下的是,有时候我们获取到的就是它的接口返回的JSON类型的数据,那么这里就需要用到python的json模块,这些等后面的训练项目出来再做分解吧。

BeautifulSoup是一个第三方库,需要单独安装,安装方式依然是用cmd(我用的是windows)命令下:

pip install beautifulsoup4
from bs4 import BeautifulSoup
# 这里注意,是从bs4里面导入beautifulsoup,且注意大小写
html_txt = '''
<html><head><title>小白学习手账-python模块:BeautifulSoup学习笔记</title></head>
<body>
<h1><b>python模块:BeautifulSoup学习笔记</b></h1>
<p class="list-item" data_id='abc123'>requests模块
<a href="http://sitea.com/requests" class="a" id="b">requests</a>
</p>
<p class="list-item" data_id='abc567'>BeautifulSoup模块
<a href="http://sitea.com/bs4" class="a" id="b">BeautifulSoup</a>
</p>
<div><h3>Life is short,you need python.</h3></div>
<p id=3 class='a1 abc1'>学习python<li>haha</li><li>hehe</li></p>
<p class="study a1"><span>训练</span></p>
'''

上面代码中,html_txt里的html代码是我们在实战爬虫项目中经常会看到的,我们要的数据会在这样的一个循环的html标签代码块中出现(有两个包含目标数据且结构相同的p标签,通常是列表页),我们开始来从这个包含有目标数据的P标签中提取数据:

soup = BeautifulSoup(html_txt,'html.parser')
# 创建一个soup对象,第一个参数是要解析的html文本,第二个参数是python内置的解析器,当然还有其他的,比如lxml
print(soup.select('.a')) # 类属性值
print(soup.select('#b')) # id属性值
# 这两个输出是一样的,这里用到的是css选择器(select方法),不同的是参数,一个粗暴点的使用技巧是:标签属性为class的,就用‘.a’,标签属性为id的,就用'#b'
下面是输出内容:

[<a class="a" href="http://sitea.com/requests" id="b">requests</a>, <a class="a" href="http://sitea.com/bs4" id="b">BeautifulSoup</a>]
[<a class="a" href="http://sitea.com/requests" id="b">requests</a>, <a class="a" href="http://sitea.com/bs4" id="b">BeautifulSoup</a>]

这里的输出是一个列表(或者叫数组),那么我现在要取链接地址和文本:

print(soup.select('.a')[0]['href'])
# 打印链接,访问数组的方法是通过索引来的,然后标签属性(下文会写)则是访问字典的方法,就是用键名
print(soup.select('.a')[0].text)
# 打印标签文本,直接text就可以了

这样,就完成了目标数据的提取了,一定要结合前面的几篇文章一起看。

好了,接下来详细说明下beautifulsoup用法:

丢几个例子:

soup.select('.list-item')  
# 等同于soup.select('p.list-item'),标签+类,当然就可以标签+Id
# 等同于soup.select('body p.list-item'),根据标签节点(类似xpath),注意是直接层级,比如这个p标签的父节点是body

[<p class="list-item" data_id="abc123">requests模块
<a class="a" href="http://sitea.com/requests" id="b">requests</a>
</p>, <p class="list-item" data_id="abc567">BeautifulSoup模块 <a class="a" href="http://sitea.com/bs4" id="b">bs4</a>
</p>]

这个例子中,我们通过select方法把class值为list-item的标签都找出来,也就是把我们上面提到的循环的p标签都提取出来了,接下来用一个for循环,再次使用访问列表的方法和select方法就能提取链接和文本了。

注意这里注释中还有标注了其他几种用法,都是用来精确定位代码块的,多值属性和多属性标签的应用,实战中那是巨普遍无比的应用了,用这个方法是屡试不爽啊,直接上代码:

soup.select('p.a1.abc1')

[<p class=”a1 abc1″ id=”3″>学习python<li>haha</li><li>hehe</li></p>]

soup.select('p.a1')

输出:
[<p class=”a1 abc1″ id=”3″>学习python<li>haha</li><li>hehe</li></p>,
<p class=”study a1″><span>训练</span></p>]

顺便取下这个目标代码块的某个属性值及所有属性,京东商城就是这么玩的O(∩_∩)O

soup.select('.list-item')[0]['data_id']
# 这里会输出'abc123'
soup.select('.list-item')[0].attrs
# attrs来输出该标签中包含的所有属性{'class': ['list-item'], 'data_id': 'abc123'}

到这里,基本可以跑到各大网站上去疯了(可不能干坏事啊。。。。)

——————拔高一丢丢的分割线————————

上面的例子用到了select(css选择器),还有个find、find_all方法,用法也类似。find_all和find方法,区别是当有多个值出现的时,find方法只返回第一个:(再说一遍:其实掌握了select基本够用啦)。

# 可以用来查找的有:标签名称、属性、标签内容、css路径、标签路径(父节点、子节点)
soup.find_all('a',class_='a') 
# 这里需要注意的是class作为参数的时候,后面要加个‘_’,你懂的
# 第一个参数是标签,第二个是属性和值,下面的不解释
soup.find_all('a',id='requests')

输出结果一样:
[<a class="a" href="http://sitea.com/requests" id="requests">requests</a>]

soup.find('a')
# 也可以直接跟标签

# 下面的用法也是会碰到的,但是相对比较少
soup.a
soup.find_all(['a','b'])
soup.find_all('p',id='3',attrs={'class':'list-item'})
# select、find_all、find都是可以交叉使用的
soup.find('p').find_all('a')
soup.find(class_='list-item').select('a')

还有个是这几天遇到的,好像是在测试拉钩网的时候碰到的,就是需要判断某个标签是否包含了某个属性,如果有包含则是我们要的数据:

soup.select('p')[0].has_attr('data_id')
# 输出 True

更多一些用法和技巧,需要在实践中才能发掘,学东西知道该怎么用就行,未必要知道她所有的用法,一通百通的事

本文首发于简书:https://www.jianshu.com/p/e52e229ddfdf

发表评论