【Python爬虫学习笔记5】Beautiful Soup库

Beautiful Soup 和 lxml 一样,是Python的一个HTML/XML的解析库,它可以借助网页的结构和属性等特性来解析网页。它和lxml有相当的功能,也有着不同之处:lxml只会局部遍历,而Beautiful Soup 是基于HTML DOM(Document Object Model)的,会载入整个文档来解析DOM树,因此时间和内存开销都会大很多,性能要低于lxml。

如下为一个解析器对比(包含正则):

解析工具解析速度使用难度
Beautiful Soup最慢最简单
lxml简单
正则最快最难

即便如此,Beautiful Soup 的解析使用相对简单,其API非常人性化,支持CSS选择器、Python标准库HTML解析器,同时也支持 lxml 的 XML解析器,甚至容错性最好的html5lib解析器。所以说,利用好Beautiful Soup可以省去很多工作,提高解析效率。

安装方法

使用pip进行安装:pip install bs4

基本使用

1.使用基础

使用前需要先导入BeautifulSoup模块(属于bs4库),然后使用Beautiful(html,parse)实例化对象,传入的参数分别为待解析的html源码文本和解析器种类(如lxml,html.parse,xml或html5lib)。当实例化对象soup后,接下来就可以调用其各个方法和属性解析HTML代码了。

html = """
<table class="tablelist" cellpadding="0" cellspacing="0"><tbody>
                <tr class="even">
                    <td class="l square"><a target="_blank" href="position_detail.php?id=44279&amp;keywords=python&amp;tid=0&amp;lid=0">28607-113 微信支付大数据平台开发工程师(深圳)</a></td>
                    <td>技术类</td>
                    <td>1</td>
                    <td>深圳</td>
                    <td>2018-09-18</td>
                </tr>
                <tr class="odd">
                    <td class="l square"><a target="_blank" href="position_detail.php?id=44274&amp;keywords=python&amp;tid=0&amp;lid=0">OMG097-自然语言处理工程师(北京)</a></td>
                    <td>技术类</td>
                    <td>3</td>
                    <td>北京</td>
                    <td>2018-09-18</td>
                </tr>
                <tr class="even">
                    <td class="l square"><a target="_blank" href="position_detail.php?id=44263&amp;keywords=python&amp;tid=0&amp;lid=0">18428-银行业务测试工程师(深圳)</a><span class="hot">&nbsp;</span></td>
                    <td>技术类</td>
                    <td>1</td>
                    <td>深圳</td>
                    <td>2018-09-18</td>
                </tr>
</tbody></table>
"""
##前期准备
from bs4 import BeautifulSoup

# 实例化对象
soup = BeautifulSoup(html, 'lxml')
# 美观地输出HTML源代码文本 print
(bs.prettify())

2.find()与find_all()方法

这两个都是Soup解析方法中较为常用的用于检索获取特定节点的方法,其中find()方法用于获取一个节点,返回值为单个的Tag标签(如果存在,否则为None,当有多个满足时只返回第一个),而find_all()则是在find()的基础上返回所有符合条件的节点列表(没有满足的情况下返回空列表[])。

通常情况下,find_all()用得更为频繁,基本语法为:object = soup.find_all(Tag),下面以一系列示例来说明其用法。

##使用find_all()检索获取节点标签
from bs4 import BeautifulSoup
html="""如上示例"""
soup = BeautifulSoup(html, 'lxml')

# 示例1——获取所有tr标签
trs = soup.find_all('tr')
for tr in trs:
    print(type(tr))    #<class 'bs4.element.Tag'>
    print(tr)

# 示例2——获取第2个tr标签
tr = soup.find_all('tr',limit=2)[1]        #参数limit用于限制返回个数为2个,由于是列表结构,第二个下标为1
print(tr)

# 示例3——获取所有class为even的tr标签
trs = soup.find_all('tr',attrs={'class':'even'})    #参数attrs用于属性过滤

# 示例4——将所有id等于test,class也等于test的a标签提取出来
aList = soup.find_all('a',attrs={'class':'test','id':'test'})

# 示例5——获取所有a标签的href属性
aList = soup.find_all('a')
for a in aList:
    href = a['href']    # 或href = a.attrs['href'],attrs为其属性字典
    print(href)

3.select()方法

此方法为CSS选择器方法,即通过元素CSS选择表达式来筛选符合条件的节点,其返回的也是为一个列表。使用此方法前需要对CSS有一定的了解,在爬虫中我们只需要掌握以下几类基本的用法即可,其他具体的可以查阅相关网络资料(比如,http://www.w3school.com.cn/cssref/css_selectors.ASP)

选择器构成法使用说明示例描述
通过标签名选择tag直接输入待选择的标签名div选择所有的div标签
通过类名选择.class在类名前面加一个.p.text选择所有类为text的p标签
通过id选择#id在id名前加一个#号#username选择id为username的标签
组合选择1(全局选择) 将多个选择器方法叠加一起,同时用空格分开p #poster选择id为poster的p标签
组合选择2(特定选择) 当需要使用组合来选择直接子节点时,需要用’>’连接div > input选择div下的直接input标签
通过属性选择[attrs=value]通过在[]中指定属性表达式来选择,但不适用多属性a[id=”link”]选择id为link的a标签

在熟悉CSS选择器基本语法规则后,我们便可以通过soup的select(选择表达式)方法来获取相应的节点标签了。以上的 select 方法返回的结果都是列表形式,可以遍历或通过下标获取节点元素,然后用使用 get_text()(返回子孙非标签字符串) 方法来获取其文本内容。

下面仍以上述html代码为例,介绍select()的使用方法。

##使用select()方法检索获取节点
from bs4 import BeautifulSoup
html="""如上示例"""
soup = BeautifulSoup(html, 'lxml')

# 示例1——获取所有tr标签
trs = soup.select('tr')
for tr in trs:
    print(tr)

# 示例2——获取第2个tr标签
tr = soup.select('tr')[1]
print(tr)

# 示例3——获取所有class为even的tr标签
trs = soup.select('tr[class="even"]')
for tr in trs:
    print(tr)

# 示例4——将所有id等于test,class也等于test的a标签提取出来
#由于CSS选择器无法直接选取同时满足两种条件的标签,故此目标无法完成,但可以通过二次选择来获取

# 示例5——获取所有a标签的href属性
aList= soup.select('a')
for a in aList:
    href = a['href']
    print(href)

4.获取文本内容

在soup获取后的节点对象中,如要获取其文本内容,除了上文中提到的get_text()方法外,还可以使用如下的属性:

(1)string:获取某个标签下的非标签字符串,返回的为字符串。

(2)strings:获取某个标签下的子孙非标签字符串,返回的为生成器。

(3)stripped_string:获取某个标签下的子孙非标签字符串,会去掉空白字符,返回的为生成器。

仍以上述为例,使用示例如下:

##获取文本内容
tr2 = soup.select('tr')[1]

# 获取非标签字符串
print(tr2.string)    #None

# 获取子孙非标签字符串
print(list(tr2.strings))    #['\n', 'OMG097-自然语言处理工程师(北京)', '\n', '技术类', '\n', '3', '\n', '北京', '\n', '2018-09-18', '\n']

# 获取除去空白的子孙非标签字符串
print(list(tr2.stripped_strings))    #['OMG097-自然语言处理工程师(北京)', '技术类', '3', '北京', '2018-09-18']

# 获取子孙非标签字符串,以普通字符串形式返回
print(tr2.get_text())
"""
Output:

OMG097-自然语言处理工程师(北京)
技术类
3
北京
2018-09-18

"""

补充内容

1.Beautiful Soup中四个常用对象:

(1)Tag

即HTML中的一个个节点标签,如head、body、title、div、p和input等等。

(2)NavigatableString

获取标签后,我们利用其属性(如string属性)从标签得到它的内容所返回的这个对象就时NavigatableString。

(3)BeautifulSoup

BeautifulSoup 对象表示的是一个文档的全部内容,大部分时候可以把它当作 Tag 对象,其支持遍历文档树和搜索文档树中描述的大部分的方法,比如我们之前使用soup就是这种对象。

(4)Comment

Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是有一类特殊对象——注释,而Comment就是用于获取这些内容的对象。实际上,Comment 对象是一个特殊的 NavigableString 对象。

html = "<p><!--Hello World--></p>"
soup = BeautifulSoup(html)
comment = soup.b.string
print(comment)    # ‘Hello World’

2.contents和children属性遍历文档树

在我们获取标签节点后,还可以通过contents和children两个属性来获取其下的子节点,二者的区别在于contents返回所有子节点列表,而children返回的是一个迭代器。

tr2 = soup.find_all('tr')[1]

# 返回所有子节点的列表
print(tr2.contents)
"""
Output:
['\n', <td class="l square"><a href="position_detail.php?id=44274&amp;keywords=python&amp;tid=0&amp;lid=0" target="_blank">OMG097-自然语言处理工程师(北京)</a></td>, '\n', <td>技术类</td>, '\n', <td>3</td>, '\n', <td>北京</td>, '\n', <td>2018-09-18</td>, '\n']
"""

# 返回所有子节点的迭代器
print(tr2.children)
"""
Output:
<list_iterator object at 0x00000224FFF01518>
"""

 


转载于:https://www.cnblogs.com/Unikfox/p/9676177.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值