Beautiful Soup 的使用

Beautiful Soup 的使用

  Beautiful Soup 就是python的一个HTML或XML的解析库,也是用于从网页中提取数据。废话不多说,直接看基本用法:

from bs4 import BeautifulSoup

html = """<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>The Dormouse's story</title>
</head>
<body>
    <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
    <p class="story">Once upon a time there were three little sisters; and their names were
        <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
        <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
        <a href="http://example.com/tittle" class="sister" id="link3">Tillie</a>;
        and they lived at the bottom of a well.
    </p>
    <p class="story">...</p>
</body>
</html>"""
soup = BeautifulSoup(html,'lxml')
print(soup.prettify())
print(soup.title.string)

 这里首先声明了html,它是一个HTML字符串,接着,将它作为第一个参数传递给BeautifulSoup对象,该对象的第二个参数为解析器的类型,此时就完成了BeautifulSoup对象的初始化。接下来就可以调用soup对象的方法和属性去解析HTML代码了。

上面的prettify方法可以把要解析的字符串以标准的缩进格式输出;soup.title.string属性实际上输出的是HTML中title标签的内容,也就是说,soup.title可以拿到HTML中的title对象,再调用string属性就可以得到里面的文本了,这比正则或是xpath都要方便很多了。

BeautifulSoup跟XPath一样,也可以获取标签的属性,子节点等等,下面来详细介绍:

 

1. 节点选择器

直接调用节点的名称就可以选择元素节点,再调用string属性就可以得到节点内的文本了。

<!--test_beautifulSoup.html-->
<!
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>The Dormouse's story</title> </head> <body> <p class="title" name="dromouse"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tittle" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well. </p> <p class="story">...</p> </body> </html>
from bs4 import BeautifulSoup
soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.title.string)
print(type(soup.p))
print(soup.p.string)

注意BeautifulSoup的第一个参数除了可以传HTML文本以外还可以传一个HTML的文件句柄。经过选择器选择后的结果都是Tag类型,这是bs4中一个重要的数据结构。另外,如果选择的对象有多个,比如上面有个p元素,而使用这种方式只会获取到第一个p元素。

2.提取信息

2.1 获取名称

可以利用name属性获取节点的名称:

from bs4 import BeautifulSoup
soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.title.name)

输出结果就是title

2.2 获取属性

每个节点都可能有一个或多个属性,比如id或者class等,选择这个节点元素后,可以调用attrs获取所有的属性:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.p.attrs)
print(soup.p.attrs['name'])

 attrs返回的结果是一个包含所有属性的字典,所以如果需要获取这个元素的属性就通过访问字典的方式来获取就可以了;其实,attrs也可以直接省略不写:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.p.attrs['name'])
print(soup.p['name'])

 上面两行的输出是一致的,需要注意的是,如果返回的结果不唯一时,就是一个列表,如果结果唯一就是一个字符串。

2.3 获取内容

通过string属性即可获取元素包含的文本内容,前面已经说了,在此就不再阐述了。

在上面的例子中,我们知道每一个返回结果都是Tag类型,它同样可以继续调用节点进行下一步的选择。比如,获取了head节点,我们可以继续用head来获取其内部的元素,这种方式称为嵌套选择:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.head.title)

在做选择的时候,很多时候不能一步就选到想要的节点元素,需要先选中某一个节点元素,然后以它为基准再选择它的子节点、父节点、兄弟节点等等,下面就来详细介绍如何选择这些节点:

子节点和子孙节点:

选取节点元素之后,如果想要获取它的直接子节点,可以调用contents属性:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.p.contents)

可以看到,返回的结果是列表形式,p节点里面既包含了文本,也包含了元素节点。除了contents属性以外,还可以通过children属性得到相应的结果:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.p.children)
for i,child in enumerate(soup.p.children):
    print(i,child)

返回的结果是生成器对象,使用for循环可以输出所有子节点。

如果需要得到所有子孙节点,可以调用descendants属性:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.p.descendants)
for i,child in enumerate(soup.p.descendants):
    print(i,child)

这里返回结果还是生成器,遍历输出就可以得到所有的子孙节点。

 父节点和祖先节点:

如果想获取某个节点的父节点,可以调用parent属性:

from bs4 import BeautifulSoup
soup = BeautifulSoup(open('./test_beautifulSoup.html'),'lxml')
print(soup.a.parent)

这里输出的仅仅是第一个a节点的直接父元素,如果想获取所有的祖先节点,可以调用parents属性,此时返回的结果是一个生成器,遍历即可获得具体的结果。

兄弟节点:

next_sibling、previous_sibling、next_siblings和previous_siblings分别获取节点的下一个兄弟元素,节点的上一个兄弟元素,节点之前所有的兄弟元素和节点之后所有的兄弟元素。

上面说到的方法都局限于只能查出一个结果就终止了,那么肯定有时候需要查找所有匹配的节点,这时候就需要用到find_all(name,attrs,recursive,text,**kwargs)方法了:

name代表节点名,attrs代表属性,text代表文本。

除此以外,还有类似的方法:

find()  匹配第一个节点

find_parents() 和 find_parent()   前者返回所有祖先节点,后者返回直接父节点

find_next_siblings() 和 find_next_sibling() 前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点

find_previous_siblings() 和 find_previous_sibling() 前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点。

find_all_next() 和 find_next() 前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。

find_all_previous() 和 find_previous() 前者返回节点后所有符合条件的节点,后者返回节点后第一个符合条件的节点。

有没有想过这么多API太复杂了,既然在操作HTML代码,如果能提供一种CSS的API那不要爽飞天了吗?是的,Beautiful Soup提供了一个select(CSS选择器字符串)方法用于获取信息。

猜你喜欢

转载自www.cnblogs.com/jonas-von/p/9179517.html