zoukankan      html  css  js  c++  java
  • Python爬虫系列(四):Beautiful Soup解析HTML之把HTML转成Python对象

    在前几篇文章,我们学会了如何获取html文档内容,就是从url下载网页。今天开始,我们将讨论如何将html转成python对象,用python代码对文档进行分析。

    (牛小妹在学校折腾了好几天,也没把html文档给分析出来。接下来的几篇文章,你可就要好好看了)

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

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

    获取和修改对象的名称及属性

    from bs4 import BeautifulSoup

    #注意,第二个参数一定是这样用字符串,照官方文档要报错。现在BeautifulSoup 是4.6
    soup = BeautifulSoup('<b class="boldest">Extremely bold</b>', "lxml-xml")
    tag = soup.b
    #b标签对应的python对象
    print(type(tag))
    print(tag.name)
    #修改标签 name 不是标签的name属性,而是标签自身
    tag.name = "blockquote"
    print(tag)
    #获取属性
    print(tag['class'])
    #获取多个属性
    print(tag.attrs)

    #修改属性
    tag['class'] = 'verybold'
    tag['id'] = 1
    print(tag)

    #删除属性
    del tag['class']
    del tag['id']
    print(tag)
    #已经没有class属性 获取就报错
    print(tag['class'])
    print(tag.get('class'))

    多指属性:

    是指一个属性有多个值。

    注意:这里使用的是 lxml-xml 解析器 所以看不出来是多值。用html。parser转出来的就是多值。

    css_soup = BeautifulSoup('<p class="body strikeout"></p>', "lxml-xml")
    print(css_soup.p['class'])

    css_soup = BeautifulSoup('<p class="body"></p>', "lxml-xml")
    print(css_soup.p['class'])

    对应结果:

    body strikeout

    body

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

    id_soup = BeautifulSoup('<p id="my id"></p>', "lxml-xml")

    #返回的是字符串
    print(id_soup.p['id'])

    将tag转换成字符串时,多值属性会合并为一个值

    rel_soup = BeautifulSoup('<p>Back to the <a rel="index">homepage</a></p>', "lxml-xml")
    print(rel_soup.a['rel'])
    rel_soup.a['rel'] = ['index', 'contents']
    print(rel_soup.p)

    展示结果:

    <p>Back to the <a rel="index contents">homepage</a></p>

    注意看a 标签的rel属性

    可以遍历的字符串

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

    soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')
    tag = soup.b
    print(tag.string)
    print(type(tag.string))

    结果:

    Extremely bold

    <class 'bs4.element.NavigableString'>

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

    from bs4 import BeautifulSoup
    from lxml.html.clean import unicode

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

    unicode_string = unicode(tag.string)
    print(unicode_string)
    结果:

    Extremely bold

    tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用 replace_with() 方法:

    from bs4 import BeautifulSoup

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

    tag.string.replace_with("No longer bold")

    print(tag)

    结果:

    <b class="boldest">No longer bold</b>

    注意:

    NavigableString 对象支持 遍历文档树 和 搜索文档树 中定义的大部分属性, 并非全部.尤其是,一个字符串不能包含其它内容(tag能够包含字符串或是其它tag),字符串不支持 .contents 或 .string 属性或 find() 方法.

    如果想在Beautiful Soup之外使用 NavigableString 对象,需要调用 unicode() 方法,将该对象转换成普通的Unicode字符串,否则就算Beautiful Soup已方法已经执行结束,该对象的输出也会带有对象的引用地址.这样会浪费内存.

    BeautifulSoup对象

    BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.

    因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name

    知道即可

    注释及特殊字符串

    Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.容易让人担心的内容是文档的注释部分

    from bs4 import BeautifulSoup, CData

    markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
    soup = BeautifulSoup(markup)
    comment = soup.b.string
    print(type(comment))
    # Comment 对象是一个特殊类型的 NavigableString 对象:
    print(comment)
    #美化后的输出结果
    print(soup.b.prettify())
    # Beautiful Soup中定义的其它类型都可能会出现在XML的文档中:
    # CData , ProcessingInstruction , Declaration , Doctype .与 Comment 对象类似,
    # 这些类都是 NavigableString 的子类,只是添加了一些额外的方法的字符串独享.
    # 下面是用CDATA来替代注释的例子:
    cdata = CData("A CDATA block")
    comment.replace_with(cdata)

    print(soup.b.prettify())
    # <b>
    # <![CDATA[A CDATA block]]>
    # </b>

  • 相关阅读:
    【leetcode】106. Construct Binary Tree from Inorder and Postorder Traversal
    【leetcode】105. Construct Binary Tree from Preorder and Inorder Traversal
    【leetcode】236. Lowest Common Ancestor of a Binary Tree
    【leetcode】235. Lowest Common Ancestor of a Binary Search Tree
    【leetcode】352. Data Stream as Disjoint Intervals
    【leetcode】897. Increasing Order Search Tree
    【leetcode】900. RLE Iterator
    BEC listen and translation exercise 26
    BEC listen and translation exercise 25
    BEC listen and translation exercise 24
  • 原文地址:https://www.cnblogs.com/zijiyanxi/p/7697699.html
Copyright © 2011-2022 走看看