BeautifulSoup的用法案例简介

在《Python爬虫利器-XPath》文中,我们介绍了XPath,使用它来进行页面文本信息提取方便快捷。在本文中,小编将介绍另外一个好用的工具–BeautifulSoup,使用它同样可以实现快速提取页面文本信息。

1.什么是BeautifulSoup

BeautifulSoup是一个从HTML或者XML文件中利用标签树功能快速提取数据的Python库。它用法简单,通过转换器把文档解析成文档树,实现查找、修改指定内容的功能。使用它,短短几行命令,就可以满足我们的大多数需求。引用方式是: from bs4 import BeautifulSoup或者import bs4。

2.用法示例

我们使用和上一篇推文中相似的HTML:

<bookstore>
<book category="Fantasy Novels">
<a href="http://blog.csdn.net/qq_36148847">链接</a>
<title lang="English">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="武侠小说">
<title lang="中文">天龙八部</title>
<author>金庸</author>
<year>2005</year>
<price>40</price>
</book>
</bookstore>

此处的HTML经解析之后,对应的子节点、父节点、兄弟节点的定义和之前推文中介绍的相同,不再赘述。

3.程序详解

3.1简单入门

我们导入指定模块,并输入该HTML:

In[1]:from bs4 import BeautifulSoup
In[2]:html ='''<bookstore><book category="Fantasy Novels"><a href="http://blog.csdn.net/qq_36148847">链接</a><title lang="English">Harry Potter</title><author>J K. Rowling</author><year>2005</year><price>29.99</price></book><book category="武侠小说"><title lang="中文">天龙八部</title><author>金庸</author><year>2005</year><price>40</price></book></bookstore>'''
In[3]:soup=BeautifulSoup(html,'xml') #将输入的html文本转换成BeautifulSoup对象
In[4]:print(type(soup))
Out[4]: <class 'bs4.BeautifulSoup'>
In[5]:print(soup)
Out[5]: <?xml version="1.0" encoding="utf-8"?>
<bookstore><book category="Fantasy Novels"><a href="http://blog.csdn.net/qq_36148847">链接</a><title lang="English">Harry Potter</title><author>J K. Rowling</author><year>2005</year><price>29.99</price></book><book category="武侠小说"><title lang="中文">天龙八部</title><author>金庸</author><year>2005</year><price>40</price></book></bookstore>

可见,解析之后的文本类型是一个bs对象。该对象相比最初的文本内容,在开头声明了xml版本以及编码类型是utf8编码,但是此时文本内容依然按原样罗列了出来,并不清晰,我们使用以下这个方法可以得到自动缩进对齐的格式。

In[6]:print(soup.prettify())
Out[6]:<?xml version="1.0" encoding="utf-8"?>
<bookstore>
 <book category="Fantasy Novels">
  <a href="http://blog.csdn.net/qq_36148847">
   链接
  </a>
  <title lang="English">
   Harry Potter
  </title>
  <author>
   J K. Rowling
  </author>
  <year>
   2005
  </year>
  <price>
   29.99
  </price>
 </book>
 <book category="武侠小说">
  <title lang="中文">
   天龙八部
  </title>
  <author>
   金庸
  </author>
  <year>
   2005
  </year>
  <price>
   40
  </price>
 </book>
</bookstore>

所以当我们不清楚当前文本内容的节点相对关系,就可以使用上述方法将其美化并打印出来。这样一来,清晰明了,赏心悦目。

我们以第一个title为例,进行解析:

In[7]:print(soup.title)
Out[7]:<title lang="English">Harry Potter</title>
In[8]:print(soup.title.name)
Out[8]:title
In[9]:print(soup.title.string)
Out[9]:Harry Potter
In[10]:print(soup.title["lang"])
Out[10]:English

可以看出,第一个title节点,它的name是title,string是对应的文本内容即Harry Potter,lang属性是English。

3.2使用不同方法提取第一个title的内容

(1)在soup下,调取第一个title节点(此处应当注意,文本中有两个title,使用“.”调取的是默认调取第一个),然后使用.string调取它的文本内容。

In[7]:print(soup.title.string)

(2)在soup下,调取第一个title节点,然后使用get_text()方法调取文本内容。

In[8]:print(soup.title.get_text())

(3)在soup下,调取第一个author节点,然后使用.previous_sibling调取上一个兄弟节点,再取其文本内容。

In[9]:print(soup.author.previous_sibling.string)

(4)在soup下,调取第一个a节点,然后使用.next_sibling调取下一个兄弟节点,再取其文本内容。

In[10]:print(soup.a.next_sibling.string)

(5)使用find方法(注:find方法默认调取第一个节点)。

In[11]:title1=soup.find("title")
In[12]:print(title1.string)

(6)使用find_all方法(注:find_all方法调取全文所有目标节点)。

In[13]:title2=soup.find_all("title",lang="English") #寻找所有title节点,而且它的lang属性为English
In[14]:for unittitle in title2:
In[15]:	print(unittitle.string)

(7)使用find_all方法:我们也可以不声明节点是什么,而只声明某一属性。

In[16]:title3=soup.find_all(lang="English") #寻找所有lang属性为English的节点
In[17]:for unittitle in title3:
In[18]:	print(unittitle.string)

以上各种方法得到的结果如下:

4.小结

以上是我们使用BeautifulSoup的惯用手法,它使用文档树这一工具配合简单的语法,轻松实现我们提取目标信息的要求。小伙伴们可以mark起来,用它来处理网页源代码吧。