当前位置: 澳门新濠3559 > 编程 > 正文

的简化与填坑,对于HTML来讲就是html.parser

时间:2019-11-08 04:40来源:编程
概述 bs4全名BeautifulSoup,是编写python爬虫常用库之一,主要用来解析html标签。 一、BeautifulSoup4   本文是对BeautifulSoup4官方文档的简化与填坑 一、初始化 from bs4 import BeautifulSoupsoup = Beau

概述

  bs4全名BeautifulSoup,是编写python爬虫常用库之一,主要用来解析html标签。

一、BeautifulSoup4

 

本文是对BeautifulSoup4官方文档的简化与填坑

一、初始化

from bs4 import BeautifulSoup

soup = BeautifulSoup("<html>A Html Text</html>", "html.parser")

  两个参数:第一个参数是要解析的html文本,第二个参数是使用那种解析器,对于HTML来讲就是html.parser,这个是bs4自带的解析器。

  如果一段HTML或XML文档格式不正确的话,那么在不同的解析器中返回的结果可能是不一样的。

解析器

使用方法

优势

Python标准库

BeautifulSoup(html, "html.parser")

1、Python的内置标准库

2、执行速度适中

3、文档容错能力强

lxml HTML

BeautifulSoup(html, "lxml")

1、速度快

2、文档容错能力强

lxml XML

BeautifulSoup(html, ["lxml", "xml"])

BeautifulSoup(html, "xml")

1、速度快

2、唯一支持XML的解析器

html5lib

BeautifulSoup(html, "html5lib")

1、最好的容错性

2、以浏览器的方式解析文档

3、生成HTML5格式的文档

格式化输出

soup.prettify()  # prettify 有括号和没括号都可以

1.1  Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:Tag,NavigableString,BeautifulSoup,Comment。

  总结来源于官方文档:

澳门新濠3559 1

二、对象

  Beautfiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:tag,NavigableString,BeautifulSoup,Comment。

二、 Tag对象:与xml或html原生文档中的对象相同

 

Beautifulsoup4

1、tag

  Tag对象与 xml 或 html 原生文档中的 tag 相同。

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')

tag = soup.b

type(tag)

# <class 'bs4.element.Tag'>

  如果不存在,则返回 None,如果存在多个,则返回第一个。

Name

  每个 tag 都有自己的名字

tag.name
# 'b'

Attributes

  tag 的属性是一个字典

tag['class']
# 'boldest'

tag.attrs
# {'class': 'boldest'}

type(tag.attrs)
# <class 'dict'>

多值属性

  最常见的多值属性是class,多值属性的返回 list。

soup = BeautifulSoup('<p class="body strikeout"></p>')

print(soup.p['class'])  # ['body', 'strikeout']

print(soup.p.attrs)     # {'class': ['body', 'strikeout']}

  如果某个属性看起来好像有多个值,但在任何版本的HTML定义中都没有被定义为多值属性,那么Beautiful Soup会将这个属性作为字符串返回。

soup = BeautifulSoup('<p id="my id"></p>', 'html.parser')
print(soup.p['id'])    # 'my id'

Text

  text 属性返回 tag 的所有字符串连成的字符串。

其他方法

  tag.has_attr('id') # 返回 tag 是否包含 id 属性

  当然,以上代码还可以写成 'id' in tag.attrs,之前说过,tag 的属性是一个字典。顺便提一下,has_的简化与填坑,对于HTML来讲就是html.parser。key是老旧遗留的api,为了支持2.2之前的代码留下的。Python3已经删除了该函数。

2.1  Tag对象的属性name:.name获取名字。

示例代码段

1.安装

2、NavigableString

  字符串常被包含在 tag 内,Beautiful Soup 用 NavigableString 类来包装 tag 中的字符串。但是字符串中不能包含其他 tag。

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')

s = soup.b.string

print(s)        # Extremely bold

print(type(s))  # <class 'bs4.element.NavigableString'>

2.2  Tag对象的属性attributes:可以被添加、删除、修改

html_doc = """
<html>
    <head><title>The Dormouse's story <!--Hey, buddy. Want to buy a used parser?-->
    <a><!--Hey, buddy. Want to buy a used parser?--></a></title>
    </head>
<body>
    <p class="title">
        <b>The Dormouse's story</b>
        <a><!--Hey, buddy. Want to buy a used parser?--></a>
    </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 link4">Elsie</a>,
        <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
        <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
        and they lived at the bottom of a well.
    </p>
    <p class="story">...</p>
"""

1.1安装Beautiful Soup4

利用python包管理工具pip可以十分简单的安装Beautiful Soup4

$ pip install beautifulsoup4 

3、BeautifulSoup

  BeautifulSoup 对象表示的是一个文档的全部内容。大部分时候,可以把它当作 Tag 对象。但是 BeautifulSoup 对象并不是真正的 HTM L或 XML 的 tag,它没有attribute属性,name 属性是一个值为“[document]”的特殊属性。

三、 BeautifulSoup对象:表示的是一个文档的全部内容,一般可以当作tag对象。他支持遍历文档树,和搜索文档树中的大部分方法。他没有name,和attribute属性。(他有个特殊属性:.name返回[document])

 

1.2安装第三方解析器lxml提高运行效率

Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml .
安装方法

$ pip install lxml

PS: win下安装lxml有坑,如果pip安装报错,参考StackOverflow上提供的解决方法

4、Comment

  Comment 一般表示文档的注释部分。

soup = BeautifulSoup("<b><!--This is a comment--></b>")

comment = soup.b.string

print(comment)          # This is a comment

print(type(comment))    # <class 'bs4.element.Comment'>

四、方法:遍历文档树

  1、快速操作:

2.使用方法

from bs4 import BeautifulSoup
soup = BeautifulSoup(open("index.html"))
print(soup.prettify())

首先,文档被转换成Unicode,并且HTML的实例都被转换成Unicode编码。然后,Beautiful Soup选择最合适的解析器来解析这段文档,如果手动指定解析器那么Beautiful Soup会选择指定的解析器来解析文档

三、遍历 

4.1  子节点(bf中字符串没有子节点):操作文档树最简单的方法就是告诉Tag的name,例如:想获取<head>标签,只需 soup.head     

soup.title  == soup.find('title')
# <title>The Dormouse's story</title>

soup.title.name
# u'title'

soup.title.string  == soup.title.text  == soup.title.get_text()
# u'The Dormouse's story'

soup.title.parent.name
# u'head'

soup.p   == soup.find('p')  # . 点属性,只能获取当前标签下的第一个标签
# <p class="title"><b>The Dormouse's story</b></p>

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

soup.a  == soup.find('a')
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

soup.find_all('a')
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

soup.find_all(['a','b'])  # 查找所有的a标签和b标签
soup.find_all(id=["link1","link2"])  # 查找所有id=link1 和id=link2的标签

soup.find(id="link3")
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>

2.1 Beautiful Soup的对象

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment .

1、子节点

contents 属性

  contents 属性返回所有子节点的列表,包括 NavigableString 类型节点。如果节点当中有换行符,会被当做是 NavigableString 类型节点而作为一个子节点。

  NavigableString 类型节点没有 contents 属性,因为没有子节点。

soup = BeautifulSoup("""<div>
test
</div>
""")

element = soup.div.contents

print(element)          # ['n', test, 'n']

children 属性

  children 属性跟 contents 属性基本一样,只不过返回的不是子节点列表,而是子节点的可迭代对象。

descendants 属性

  descendants 属性返回 tag 的所有子孙节点。

string 属性

  当 tag 仅有一个 NavigableString 类型子节点,string 属性返回这个NavigableString 类型子节点。

  如果 tag 仅有一个子节点(子节点也可以有一个子节点,递归),string 属性返回最后一个 tag 的 string 属性值。

soup = BeautifulSoup("""<div>
    <p><b>test</b></p>
</div>
""")

element = soup.p.string

print(element)          # test

print(type(element))    # <class 'bs4.element.NavigableString'>

  特别注意,为了清楚显示,一般我们会将 html 节点换行缩进显示,而在BeautifulSoup 中会被认为是一个 NavigableString 类型子节点,导致出错。上例中,如果改成 element = soup.div.string 就会出错。

strings 和 stripped_strings 属性

  如果 tag 中包含多个字符串,可以用 strings 属性来获取。如果返回结果中要去除空行,则可以用 stripped_strings 属性。

soup = BeautifulSoup("""<div>
    <p>      </p>
    <p>test 1</p>
    <p>test 2</p>
</div>
""", 'html.parser')

element = soup.div.stripped_strings

print(list(element))          # ['test 1', 'test 2']

        soup.标签名

  2、Beautiful Soup对象有四种类型:

Tag

Tag 对象与XML或HTML原生文档中的tag相同:

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')
tag = soup.b
type(tag)
# <class 'bs4.element.Tag'>

Tag中有name和attributes属性

tag.name
# u'b'
tag['class']
# u'boldest'

tag的属性可以被添加,删除或修改. 再说一次, tag的属性操作方法与字典一样

2、父节点

parent 属性

  parent 属性返回某个元素(tag、NavigableString)的父节点,文档的顶层节点的父节点是 BeautifulSoup 对象,BeautifulSoup 对象的父节点是 None。

parents 属性

  parent 属性递归得到元素的所有父辈节点,包括 BeautifulSoup 对象。

       .contents  将tag的子节点以列表方式输出、.children 可以对Tag的子节点进行循环。(输出子节点)

    1、BeautifulSoup

NavigableString(可以遍历的字符串)

字符串常被包含在tag内.Beautiful Soup用 NavigableString 类来包装tag中的字符串:

tag.string
# u'Extremely bold'
type(tag.string)
# <class 'bs4.element.NavigableString'>

一个 NavigableString字符串与Python中的Unicode字符串相同,并且还支持包含在 遍历文档树 和 搜索文档树 中的一些特性. 通过 unicode()方法可以直接将 NavigableString对象转换成Unicode字符串:

unicode_string = unicode(tag.string)
unicode_string
# u'Extremely bold'
type(unicode_string)
# <type 'unicode'>

3、兄弟节点

next_sibling 和 previous_sibling

  next_sibling 返回后一个兄弟节点,previous_sibling 返回前一个兄弟节点。直接看个例子,注意别被换行缩进搅了局。

soup = BeautifulSoup("""<div>
    <p>test 1</p><b>test 2</b><h>test 3</h></div>
""", 'html.parser')

print(soup.b.next_sibling)      # <h>test 3</h>

print(soup.b.previous_sibling)  # <p>test 1</p>

print(soup.h.next_sibling)      # None

next_siblings 和 previous_siblings

  返回可迭代类型,不赘述。

      .descondants 可以对Tag的所有子孙节点进行输出。

    2、tag:标签

BeautifulSoup

BeautifulSoup
对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag
对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.
因为 BeautifulSoup对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name属性是很方便的,所以 BeautifulSoup对象包含了一个值为 “[document]” 的特殊属性 .name

soup.name
# u'[document]'

4、回退和前进

  把html解析看成依次解析标签的一连串事件,BeautifulSoup 提供了重现解析器初始化过程的方法。

  next_element 属性指向解析过程中下一个被解析的对象(tag 或 NavigableString)。

  previous_element 属性指向解析过程中前一个被解析的对象。

  另外还有next_elements 和 previous_elements 属性,不赘述了。

      .string 如果tag只有NavigableString类型子节点,可以用.stirng获取子节点。

    3、NavigableString  : 标签中的文本,可包含注释内容

Comment(注释及特殊字符串)

Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.容易让人担心的内容是文档的注释部分
PS:由于爬虫一般不需要爬注释,不展开。

四、搜索

       .stripped_strings可以去除多余的空格。

    4、Comment :标签中的注释,纯注释,没有正文内容

2.2 遍历文档树

PS:树,好大的树

1、过滤器

  介绍 find_all() 方法前,先介绍一下过滤器的类型,这些过滤器贯穿整个搜索的API。过滤器可以被用在tag的name中,节点的属性中,字符串中或他们的混合中。

示例使用的 html 文档如下:

html = """
<div>
    <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 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/tillie" class="sister" id="link3">Tillie</a></p>
</div>
"""

soup = BeautifulSoup(html, 'html.parser')

字符串

查找所有的<b>标签

soup.find_all('b')  # [<b>The Dormouse's story</b>]

正则表达式

传入正则表达式作为参数,返回满足正则表达式的标签。下面例子中找出所有以b开头的标签。

soup.find_all(re.compile("^b"))  # [<b>The Dormouse's story</b>]

列表

传入列表参数,将返回与列表中任一元素匹配的内容。下面例子中找出所有<a>标签和<b>标签。

soup.find_all(["a", "b"])

True

True可以匹配任何值,下面的代码查找到所有的tag,但是不会返回字符串节点。

soup.find_all(True)

方法

如果没有合适过滤器,那么还可以自定义一个方法,方法只接受一个元素参数,如果这个方法返回True表示当前元素匹配被找到。下面示例返回所有包含 class 属性但不包含 id 属性的标签。

def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')


print(soup.find_all(has_class_but_no_id))

返回结果:

[<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="link3">Tillie</a></p>]

这个结果乍一看不对,<a>标签含有 id 属性,其实返回的 list 中只有2个元素,都是<p>标签,<a>标签是<p>标签的子节点。

4.2  父节点

 

获取标签内容:

获取标签内容和剥洋葱差不多

soup = '''
<head><title>The Dormouse's story</title></head>
<title>Another Dormouse's story</title>
'''
soup.head
# <head><title>The Dormouse's story</title></head>
soup.head.title
# <title>The Dormouse's story</title>
soup.title 
# <title>The Dormouse's story</title>
soup.title.string
The Dormouse's story

可以看到使用title只能获取到第一个title,可以用find_all()需要获取所有title,并返回一个list:

soup.find_all('title')
# [<title>The Dormouse's story</title>,<title>Another Dormouse's story</title>]

2、find 和 find_all

  搜索当前 tag 的所有 tag 子节点,并判断是否符合过滤器的条件

语法:

  find(name=None, attrs={}, recursive=True, text=None, **kwargs)

  find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)

参数:

  name:查找所有名字为 name 的 tag,字符串对象会被自动忽略掉。上面过滤器示例中的参数都是 name 参数。当然,其他参数中也可以使用过滤器。

  attrs:按属性名和值查找。传入字典,key 为属性名,value 为属性值。

  recursive:是否递归遍历所有子孙节点,默认 True。

  text:根据标签的文本内容去查找标签列表,通常配合正则表达式使用

  limit:限定返回列表的最大个数。

  kwargs:如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作 tag 的属性来搜索。这里注意,如果要按 class 属性搜索,因为 class 是 python 的保留字,需要写作 class_。

 

  Tag 的有些属性在搜索中不能作为 kwargs 参数使用,比如 html5 中的 data-* 属性。

data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')

print(data_soup.find_all(data-foo="value"))

# SyntaxError: keyword can't be an expression

  但是可以通过 attrs 参数传递:

data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')

print(data_soup.find_all(attrs={"data-foo": "value"}))

# [<div data-foo="value">foo!</div>]

  而按 class_ 查找时,只要一个CSS类名满足即可,如果写了多个CSS名称,那么顺序必须一致,而且不能跳跃。以下示例中,前三个可以查找到元素,后两个不可以。

css_soup = BeautifulSoup('<p class="body bold strikeout"></p>')

print(css_soup.find_all("p", class_="strikeout"))

print(css_soup.find_all("p", class_="body"))

print(css_soup.find_all("p", class_="body bold strikeout"))

# [<p class="body strikeout"></p>]

print(css_soup.find_all("p", class_="body strikeout"))

print(css_soup.find_all("p", class_="strikeout body"))

# []

       .parent 来获取父节点,文档的顶层节点比如的父节点是BeautifulSoup对象,BeautifulSoup对象的.parent是None。

  标签属性的操做跟字典是一样一样的

.contents ,.children,.descendants:

.contents 和 .children 属性仅包含tag的直接子节点
.contents 属性相当于剥一层洋葱皮,并返回list:

head_tag = '''
<head><title>The Dormouse's story</title><title>Another Dormouse's story</title></head>
'''
head_tag.content
# [<title>The Dormouse's story</title>, <title>Another Dormouse's story</title>]

.children是列表迭代器,用for输出:

html_doc = """<head><title>The Dormouse's story</title><title>T Dormouse's story</title></head>"""

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc,'lxml')

print(soup.head.children)
for child in soup.head.children:
    print(child)
# <list_iterator object at 0x10b66c710>
# <title>The Dormouse's story</title>
# <title>T Dormouse's story</title> 

.descendants 属性和.children类似,不同的是.children只能访问一层子节点,而可以对所有tag的子孙节点进行递归循环

3、像调用find_all()一样调用tag

  find_all() 几乎是 BeautifulSoup 中最常用的搜索方法,所以我们定义了它的简写方法。BeautifulSoup 对象和 tag 对象可以被当作一个方法来使用,这个方法的执行结果与调用这个对象的 find_all() 方法相同,下面两行代码是等价的:

soup.find_all('b')

soup('b')

       .parents  获取所有父节点。

  html多值属性(xml不适合):

.strings 和以及更好的 stripped_strings

如果tag中包含多个字符串 ,可以使用 .strings来循环获取,stripped_strings用于去除所有空白内容,包括段落间空行:

4、其他搜索方法

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()

       .next_sibling 和 .previous_sibling

    意思为一个属性名称,它是多值的,即包含多个属性值,即使属性中只有一个值也返回值为list,

.parent和.parents

.parent 属性可以用来获取某个元素的父节点,.parents 属性可以递归得到元素的所有父辈节点

五、CSS选择器

BeautifulSoup支持大部分的CSS选择器,这里直接用代码来演示。

from bs4 import BeautifulSoup


html = """
<html>
<head><title>标题</title></head>
<body>
 <p class="title" name="dromouse"><b>标题</b></p>
 <div name="divlink">
  <p>
   <a href="http://example.com/1" class="sister" id="link1">链接1</a>
   <a href="http://example.com/2" class="sister" id="link2">链接2</a>
   <a href="http://example.com/3" class="sister" id="link3">链接3</a>
  </p>
 </div>
 <p></p>
 <div name='dv2'></div>
</body>
</html>
"""

soup = BeautifulSoup(html, 'lxml')

# 通过tag查找
print(soup.select('title'))             # [<title>标题</title>]

# 通过tag逐层查找
print(soup.select("html head title"))   # [<title>标题</title>]

# 通过class查找
print(soup.select('.sister'))
# [<a class="sister" href="http://example.com/1" id="link1">链接1</a>,
# <a class="sister" href="http://example.com/2" id="link2">链接2</a>,
# <a class="sister" href="http://example.com/3" id="link3">链接3</a>]


# 通过id查找
print(soup.select('#link1, #link2'))
# [<a class="sister" href="http://example.com/1" id="link1">链接1</a>,
# <a class="sister" href="http://example.com/2" id="link2">链接2</a>]


# 组合查找
print(soup.select('p #link1'))    # [<a class="sister" href="http://example.com/1" id="link1">链接1</a>]


# 查找直接子标签
print(soup.select("head > title"))  # [<title>标题</title>]

print(soup.select("p > #link1"))   # [<a class="sister" href="http://example.com/1" id="link1">链接1</a>]

print(soup.select("p > a:nth-of-type(2)"))  # [<a class="sister" href="http://example.com/2" id="link2">链接2</a>]
# nth-of-type 是CSS选择器



# 查找兄弟节点(向后查找)
print(soup.select("#link1 ~ .sister"))
# [<a class="sister" href="http://example.com/2" id="link2">链接2</a>,
# <a class="sister" href="http://example.com/3" id="link3">链接3</a>]

print(soup.select("#link1 + .sister"))
# [<a class="sister" href="http://example.com/2" id="link2">链接2</a>]



# 通过属性查找
print(soup.select('a[href="http://example.com/1"]'))

# ^ 以XX开头
print(soup.select('a[href^="http://example.com/"]'))

# * 包含
print(soup.select('a[href*=".com/"]'))

# 查找包含指定属性的标签
print(soup.select('[name]'))



# 查找第一个元素
print(soup.select_one(".sister"))

 

新建了微信公众号,会将文章同步到公众号上,感兴趣的朋友可以关注一下。

澳门新濠3559 2

 

      .next_sibling和.previous_sibling  属性来查询兄弟节点

    如:class,rel , rev , accept-charset , headers , accesskey

兄弟节点

      .next_siblings 和 .previous_siblings  通过.next_siblings和.previous_siblings属性可以对当前节点的兄弟节点迭代输出

    其它属性为单值属性,即使属性值中有多个空格隔开的值,也是反回一个字符串

.next_sibling 和 .previous_sibling,.next_siblings 和 .previous_siblings:

在文档树中,使用 .next_sibling 和 .previous_sibling 属性来查询兄弟节点,通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出:

     .next_element属性指向解析过程中下一个被解析的对象(字符串或tag),结果可能与.next_sibling相同,但通常是不一样的.

soup.a['class']  #['sister']


id_soup = BeautifulSoup('<p id="my id"></p>')
id_soup.p['id']  #'my id'

回退和前进

     .previous_element属性刚好与.next_element相反,它指向当前被解析的对象的前一个解析对象.

 

.next_element 和 .previous_element,.next_elements 和 .previous_elements

.next_element 属性指向解析过程中下一个被解析的对象(字符串或tag),结果可能与 .next_sibling 相同,但通常是不一样的.通过 .next_elements 和 .previous_elements 的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样.

      .next_elements和.previous_elements的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样

  3、html中tag内容输出: 

2.3搜索文档树

4.3 过滤器

    string:输出单一子标签文本内容或注释内容(选其一,标签中包含两种内容则输出为None)

find_all()

使用 find_all() 类似的方法可以查找到想要查找的文档内容,find_all( name , attrs , recursive , text , **kwargs )

  • name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.
  • 如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.搜索指定名字的属性时可以使用的参数值包括 字符串 , 正则表达式 , 列表, True .
  • 按照CSS类名搜索tag的功能非常实用,但标识CSS类名的关键字 class 在Python中是保留字,使用 class 做参数会导致语法错误.从Beautiful Soup的4.1.1版本开始,可以通过 class_ 参数搜索有指定CSS类名的tag:
  • 通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True . 看例子:
  • find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.
  • 调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False
find_all('b')
# 返回所有b标签


import re
for tag in soup.find_all(re.compile("^b")):
    print(tag.name)
# body
# b
# 通过正则表达式返回含有b开头的标签


soup.find_all(["a", "b"])
# 返回含有a或b标签的


def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')
soup.find_all(has_class_but_no_id)
# [<p class="title"><b>The Dormouse's story</b></p>,
#  <p class="story">Once upon a time there were...</p>,
#  <p class="story">...</p>]
# 自定一种方法

1.字符串  

    strings: 返回所有子孙标签的文本内容的生成器(不包含注释)

find()

find('tag')相当于find_all('tag',limit = 1)

澳门新濠3559 3

    stripped_strings:返回所有子孙标签的文本内容的生成器(不包含注释,并且在去掉了strings中的空行和空格)

find_next_siblings() 合 find_next_sibling(),find_澳门新濠3559,previous_siblings() 和 find_previous_sibling()

find_next_siblings( name , attrs , recursive , text , **kwargs )
find_next_sibling( name , attrs , recursive , text , **kwargs )
这2个方法通过 .next_siblings 属性对当tag的所有后面解析 [5] 的兄弟tag节点进行迭代, find_next_siblings() 方法返回所有符合条件的后面的兄弟节点, find_next_sibling() 只返回符合条件的后面的第一个tag节点.
ind_previous_siblings( name , attrs , recursive , text , **kwargs )
find_previous_sibling( name , attrs , recursive , text , **kwargs )
这2个方法通过 .previous_siblings 属性对当前tag的前面解析 [5] 的兄弟tag节点进行迭代, find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点, find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点

  1. 正则表达式

    text:只输出文本内容,可同时输出多个子标签内容

find_all_next() 和 find_next(),find_all_previous() 和 find_previous()

find_all_next( name , attrs , recursive , text , **kwargs ),find_next( name , attrs , recursive , text , **kwargs )
这2个方法通过 .next_elements 属性对当前tag的之后的tag和字符串进行迭代, find_all_next() 方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点
find_all_previous( name , attrs , recursive , text , **kwargs ),find_previous( name , attrs , recursive , text , **kwargs )
这2个方法通过 .previous_elements 属性对当前节点前面 [5] 的tag和字符串进行迭代, find_all_previous() 方法返回所有符合条件的节点, find_previous() 方法返回第一个符合条件的节点.

澳门新濠3559 4

    get_text():只输出文本内容,可同时输出多个子标签内容

2.4 CSS选择器

W3School上有关CSS选择器相关介绍

  1. 列表

  string:

2.5 修改文档树

由于目前我接触到的爬虫都很少涉及到修改数据,有需要自行参看Beautifulsoup官方文档

澳门新濠3559 5

markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup = BeautifulSoup(markup, 'html.parser')
comm = soup.b.string
print(comm)  # Hey, buddy. Want to buy a used parser?
print(type(comm))  #<class 'bs4.element.Comment'>

2.6 输出

  1. true :True可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点

   strings:

get_text()

如果只想得到tag中包含的文本内容,那么可以嗲用 get_text() 方法,这个方法获取到tag中包含的所有文版内容包括子孙tag中的内容,并将结果作为Unicode字符串返回:

PS:其他内容请查看官方文档

4.4  方法

head_tag = soup.body
for s in head_tag.strings:
    print(repr(s))

结果:
'n'
"The Dormouse's story"
'n'
'Once upon a time there were three little sisters; and their names weren        '
'Elsie'
',n        '
'Lacie'
' andn        '
'Tillie'
';n        and they lived at the bottom of a well.n    '
'n'
'...'
'n'

如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数[4],如果这个方法返回True表示当前元素匹配并且被找到,如果不是则反回False

  stripped_strings:

1.  find_all()

head_tag = soup.body
for s in head_tag.stripped_strings:
    print(repr(s))

结果:
"The Dormouse's story"
'Once upon a time there were three little sisters; and their names were'
'Elsie'
','
'Lacie'
'and'
'Tillie'
';n        and they lived at the bottom of a well.'
'...'

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

  text:

find_all()方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件.

soup = BeautifulSoup(html_doc, 'html.parser')
head_tag = soup.body
print(head_tag.text)

结果:
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.

...

soup = BeautifulSoup(html_doc, 'html.parser')
head_tag = soup.body
print(repr(head_tag.text))

结果:
"nThe Dormouse's storynOnce upon a time there were three little sisters; and their names weren        Elsie,n        Lacie andn        Tillie;n        and they lived at the bottom of a well.n    n...n"

2.  name

 

name参数可以查找所有名字为name的tag,字符串对象会被自动忽略掉.

 

  1. keywork

  4、返回子节点列表:

  1. 按css搜索  按照CSS类名搜索tag的功能非常实用

    .contents: 以列表的方式返回节点下的直接子节点

soup.find_all("a",class_="sister")

    .children:以生成器的方式反回节点下的直接子节点

soup.find_all(class_=re.compile("itl"))

soup = BeautifulSoup(html_doc, 'html.parser')
head_tag = soup.head
print(head_tag)
print(head_tag.contents)
print(head_tag.contents[0])
print(head_tag.contents[0].contents)

for ch in head_tag.children:
    print(ch)

结果:
<head><title>The Dormouse's story</title></head>
[<title>The Dormouse's story</title>]
<title>The Dormouse's story</title>
["The Dormouse's story"]
<title>The Dormouse's story</title>

soup.find_all("a",attrs={"class":"sister"})

 

5.text参数

  5、返回子孙节点的生成器:

通过text参数可以搜搜文档中的字符串内容.

     .descendants: 以列表的方式返回标签下的子孙节点

澳门新濠3559 6

for ch in head_tag.descendants:
    print(ch)

结果:
<title>The Dormouse's story</title>
The Dormouse's story

澳门新濠3559 7

 

  1. limit参数

  6、父标签(parent):如果是bs4对象,不管本来是标签还是文本都可以找到其父标签,但是文本对象不能找到父标签

澳门新濠3559 8

soup = BeautifulSoup(html_doc, 'html.parser')
tag_title = soup.b  # b标签
print(tag_title.parent)  # b标签的父标签 p
print(type(tag_title.string))  # b标签中的文本的类型,文本中有注释时结果为None <class 'bs4.element.NavigableString'>
print(tag_title.string.parent)  # b标签中文本的父标签 b
print(type(tag_title.text))  # b 标签中的文本类型为str,无bs4属性找到父标签
  1. recursive

 

调用tag的find_all()方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数recursive=False.

  7、递归父标签(parents):递归得到元素的所有父辈节点

澳门新濠3559 9

soup = BeautifulSoup(html_doc, 'html.parser')
link = soup.a
for parent in link.parents:
    print(parent.name)

结果:

待续。。。

p
body
html
[document]

 

  8、前后节点查询(不是前后标签哦,文本也是节点之一):previous_sibling,next_sibling

澳门新濠3559 10

 

   9、以生成器的方式迭代返回所有兄弟节点

for sib in soup.a.next_siblings:
    print(sib)
    print("---------")

结果:
-------------
,

---------
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
---------


---------
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
---------
;
        and they lived at the bottom of a well.

---------

 

  10、搜索文档树

    过滤器:

      1、字符串

      2、正则表达式

      3、列表

      4、True

      5、方法

html_doc = """<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</p>
<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/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.

<p class="story">...</p>
</body>
"""
from bs4 import BeautifulSoup
import re
soup = BeautifulSoup(html_doc, 'html.parser')
soup.find_all("a")  # 字符串参数
soup.find_all(re.compile("^b"))  # 正则参数
soup.find_all(re.compile("a"))  # 正则参数
soup.find_all(re.compile("l$"))  # 正则参数
soup.find_all(["a", "b"])  # 标签的列表参数
soup.find_all(True)  # 返回所有标签
def has_class_no_id(tag):
    return tag.has_attr("class") and not tag.has_attr("id")
soup.find_all(has_class_no_id)  # 方法参数

 

  11、find选择器:

    语法 :

    # find_all( name , attrs , recursive , text , **kwargs )
    #  name :要查找的标签名
    #  attrs: 标签的属性
    #  recursive: 递归
    #  text: 查找文本
    # **kwargs :其它 键值参数

  特殊情况:
    data-foo="value",因中横杠不识别的原因,只能写成attrs={"data-foo":"value"},

    class="value",因class是关键字,所以要写成class_="value"或attrs={"class":"value"}

from bs4 import BeautifulSoup
import re
html_doc = """
<html><head><title>The Dormouse's story</title></head>

<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 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/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

# find_all( name , attrs , recursive , text , **kwargs )
#  name :要查找的标签名(字符串、正则、方法、True)
#  attrs: 标签的属性
#  recursive: 递归
#  text: 查找文本
# **kwargs :其它 键值参数
soup = BeautifulSoup(html_doc, 'html.parser')
print(soup.find_all('p', 'title')) # p标签且class="title"
soup.find_all('title')  # 以列表形式返回 所有title标签a
soup.find_all(attrs={"class":"sister"})  # 以列表形式返回 所有class属性==sister的标签
soup.find_all(id='link2')  # 返回所有id属性==link2的标签
soup.find_all(href=re.compile("elsie")) # 返回所有href属性包含elsie的标签
soup.find_all(id=True)  # 返回 所有包含id属性的标签
soup.find_all(id="link1", href=re.compile('elsie'))  #  id=link1且href包含elsie

澳门新濠3559 11

关于class的搜索

soup = BeautifulSoup(html_doc, 'html.parser')
css_soup = BeautifulSoup('<p class="body strikeout"></p>', 'html.parser')
css_soup.find_all("p", class_="body")  # 多值class,指定其中一个即可
css_soup.find_all("p", class_="strikeout")
css_soup.find_all("p", class_="body strikeout")  # 精确匹配
# text 参数可以是字符串,列表、方法、True
soup.find_all("a", text="Elsie")  # text="Elsie"的a标签

 

  12、父节点方法:

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

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

html_doc = """<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</p>
    <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
    <p>
        <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
    </p>
    <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
    and they lived at the bottom of a well.
    <p class="story">...</p>
</body>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
a_string = soup.find(text="Lacie")  # 文本为Lacie的节点
type(a_string), a_string  # <class 'bs4.element.NavigableString'> Lacie
a_parent = a_string.find_parent()  # a_string的父节点中的第一个节点
a_parent = a_string.find_parent("p")  # a_string的父节点中的第一个p节点
a_parents = a_string.find_parents()  # a_string的父节点
a_parents = a_string.find_parents("a")  # a_string的父点中所有a节点

 

  13、后面的邻居节点:

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

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

html_doc = """<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</p>
    <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
    <b href="http://example.com/elsie" class="sister" id="link1">Elsie</b>,
    <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
    <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
        and they lived at the bottom of a well.
    <p class="story">...</p>
</body>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
first_link = soup.a  # 第一个a标签
a_sibling = first_link.find_next_sibling()  # 后面邻居的第一个
a_sibling = first_link.find_next_sibling("a")  # 后面邻居的第一个a
a_siblings = first_link.find_next_siblings()  # 后面的所有邻居
a_siblings = first_link.find_next_siblings("a")  # 后面邻居的所有a邻居

 

   14、前面的邻居节点:

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

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

 

  15、后面的节点:

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

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

html_doc = """<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</p>
    <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
    <p>
        <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
    </p>
    <p>
        <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
    </p>
        and they lived at the bottom of a well.
    <p class="story">...</p>
</body>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
a_string = soup.find(text="Lacie")
a_next = a_string.find_next()  # 后面所有子孙标签的第一个
a_next = a_string.find_next('a')  # 后面所有子孙标签的第一个a标签
a_nexts = a_string.find_all_next()  # 后面的所有子孙标签
a_nexts = a_string.find_all_next('a')  # 后面的所有子孙标签中的所有a标签

 

   16、前面的节点:

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

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

 

  17、解析部分文档:

    如果仅仅因为想要查找文档中的<a>标签而将整片文档进行解析,实在是浪费内存和时间.最快的方法是从一开始就把<a>标签以外的东西都忽略掉. SoupStrainer 类可以定义文档的某段内容,这样搜索文档时就不必先解析整篇文档,只会解析在 SoupStrainer 中定义过的文档. 创建一个 SoupStrainer 对象并作为 parse_only 参数给 BeautifulSoup 的构造方法即可。

SoupStrainer 类参数:name , attrs , recursive , text , **kwargs

html_doc = """<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 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/tillie" class="sister" id="link3">Tillie</a>;
    </p>
        and they lived at the bottom of a well.
    <p class="story">...</p>
</body>
"""
from bs4 import SoupStrainer
a_tags = SoupStrainer('a')  # 所有a标签
id_tags = SoupStrainer(id="link2")  # id=link2的标签
def is_short_string(string):
    return len(string) < 10  # string长度小于10,返回True
short_string = SoupStrainer(text=is_short_string)  # 符合条件的文本

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser', parse_only=a_tags).prettify()
soup = BeautifulSoup(html_doc, 'html.parser', parse_only=id_tags).prettify()
soup = BeautifulSoup(html_doc, 'html.parser', parse_only=short_string).prettify()

 

编辑:编程 本文来源:的简化与填坑,对于HTML来讲就是html.parser

关键词:

  • 上一篇:没有了
  • 下一篇:没有了