python爬虫基础html内容解析库BeautifulSoup

我们通过Requests请求url获取数据,请求把数据返回来之后就要提取目标数据,不同的网站返回的内容通常有多种不同的格式,一种是 json 格式,我们可以直接通过json.loads转换python的json对象处理。另一种 XML 格式的,还有一种最常见格式的是 HTML 文档,今天就来讲讲如何从 HTML 中提取出感兴趣的数据。

BeautifulSoup 是一个用于解析 HTML 文档的 Python 库,通过 BeautifulSoup,你只需要用很少的代码就可以提取出 HTML 中任何感兴趣的内容,此外,它还有一定的 HTML 容错能力,对于一个格式不完整的HTML 文档,它也可以正确处理。

安装 beautifulsoup

pip install beautifulsoup4

初始化对象时可以直接传递字符串或者文件句柄

soup = BeautifulSoup(open("index.html"))
soup = BeautifulSoup("data")

支持多种解析接口

# python内置HTML解析
BeautifulSoup(markup, "html.parser")
# lxml语言支持HTML解析
BeautifulSoup(markup, "lxml")
# 解析XML引擎
BeautifulSoup(markup, "xml")
# 解析HTML5引擎
BeautifulSoup(markup, "html5lib")

自动添加和补全标签

下面是一段不规范的html,缺少闭合标签

html_doc = """
The Dormouse's story

The Dormouse's story

Once upon a time there were three little sisters; and their names were Elsie, Lacie and Tillie; and they lived at the bottom of a well.

...

"""
  • 它由很多标签(Tag)组成,比如 html、head、title等等都是标签
  • 一个标签对构成一个节点,比如 …是一个根节点
  • 节点之间存在某种关系,比如p之间互为邻居,他们是相邻的兄弟(sibling)节点
  • p 是 body 的直接子(children)节点,还是 html 的子孙(descendants)节点
  • body 是 p 的父(parent)节点,html 是 p 的祖辈(parents)节点
  • 嵌套在标签之间的字符串是该节点下的一个特殊子节点,比如title文本内容“The Dormouse’sstory”也是一个节点,只不过没名字。

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
print(soup.prettify())

prettify()标准缩进格式的输出。输出内容如下:

 <html>
  <head>
   <title>
   The Dormouse's story
   title>
  head>
  <body>
   <p class="title">
    <b>
     The Dormouse's story
    b>
   p>
   <p class="story">
   Once upon a time there were three little sisters; and their names were
    <a class="sister" href="http://example.com/elsie" id="link1">
     Elsie
    a>
    ,
    <a class="sister" href="http://example.com/lacie" id="link2">
     Lacie
    a>
    and
    <a class="sister" href="http://example.com/tillie" id="link2">
     Tillie
    a>
    ; and they lived at the bottom of a well.
  p>
   <p class="story">
    ...
   p>
  body>
 html>

bs4获取标签及内容示例


# title标签
soup.title
# The Dormouse's story

# title标签名称
soup.title.name
# 'title'

# # title标签的文本字符内容
soup.title.string
# 'The Dormouse's story'

# title标签父节点名称
soup.title.parent.name
# 'head'

# 从前向后找到html孙节点第一个p节点
soup.p
# 

The Dormouse's story

# p节点的class属性 soup.p['class'] # ['title'] # 进栈出栈的方式找到第一个a标签 soup.a # Elsie # p节点的href属性 soup.a["href"] # 'http://example.com/elsie' soup.find_all('a') # 同上 soup.find_all("p")[1].find_all("a") # [Elsie, # Lacie, # Tillie] soup.find(id="link3") # Tillie

遍历文档树

从根节点 html 标签开始遍历,元素进栈出栈,直到找到目标元素为止。

BeatifulSoup 将 HTML 抽象成为 4 类主要的数据类型:

  • Tag:每个标签节点就是一个Tag对象
  • NavigableString:包裹在Tag对象里的文本字符串
  • BeautifulSoup 对象代表要解析的整个
  • Comment注释对象

type(soup)
# 
type(soup.p)
# 
# type(soup.p.string)
<class 'bs4.element.NavigableString'>

Tag标签

每个 Tag 都有一个名字,它对应 HTML 的标签名称。

soup.p.name
# 'p'

标签有属性,属性的访问方式和字典是类似的,它返回一个列表对象或字符串。

soup.p['class']
# ['title']

soup.a['href']
# 'http://example.com/elsie'

NavigableString
获取标签中的内容,直接使用 .stirng 即可获取,它是一个 NavigableString 对象 。

soup.p.string
# "The Dormouse's story"
type(soup.p.string)
bs4.element.NavigableString

搜索文档树

搜索文档树是通过指定标签名来搜索元素,还可以通过指定标签的属性值来精确定位某个节点元素,最常用的两个方法就是 find 和 find_all。这两个方法在 BeatifulSoup 和 Tag 对象上都可以被调用。

find_all()方法

find_all( name , attrs , recursive , text , **kwargs )

第一个参数 name 是标签节点的名字。

# 所有p标签
soup.find_all("p")

# [

The Dormouse's story

,
#

Once upon a time there were three little sisters; and their names were # Elsie, # Lacie and # Tillie; # and they lived at the bottom of a well.

,
#

...

]

第二个参数是标签的class属性值

soup.find_all("p","title")
# 同上
soup.find_all("p",class_ ="title")

# [

The Dormouse's story

]

kwargs 是标签的属性名值对。

import re
# 支持使用标签属性
soup.find_all(href="http://example.com/lacie")
soup.find_all(id="link2")

# 支持使用正则
soup.find_all(href=re.compile("lacie"))
 
# [Lacie]

# 支持使用布尔类型
soup.find_all('a',id=True)

遍历和搜索相结合,先定位到 body 标签,再从 body 中找 a 标签.。

soup.body.find_all('a',id=True)

find()方法

find 方法跟 find_all 类似,唯一不同的地方是,它返回的单个 Tag 对象而非列表,如果没找到匹配的节点则返回 None。如果匹配多个 Tag,只返回第0个。

soup.body.find("a")
# Elsie

get_text()方法
获取标签里面内容,除了可以使用 .string 之外,还可以使用 get_text 方法,不同的地方在于前者返回的一个 NavigableString 对象,后者返回的是 字符串。

soup.body.find("a").get_text()
# Elsie

实际场景中我们一般使用 get_text 方法获取标签中的内容。

总结:

通过beautifulsoup我们能够解析大部分静态html网页,遍历和搜索组合方式定位html的标签,并获取相应标签的内容。

python爬虫基础html内容解析库BeautifulSoup_第1张图片

你可能感兴趣的:(Python,python办公自动化,网络爬虫,python,爬虫,html)