zoukankan      html  css  js  c++  java
  • beautifulsoup

      pip install beautifulsoup4

        pip install lxml

        pip install html5lib

      建议安装lxml作为解析器,因为速度快,文档容错能力强,效率

    2、简单使用

    HTML文档:

    <!DOCTYPE html>
    <html>
    <head>
        <meta content="text/html;charset=utf-8" http-equiv="content-type" />
        <meta content="IE=Edge" http-equiv="X-UA-Compatible" />
        <meta content="always" name="referrer" />
        <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css" />
        <title>百度一下,你就知道 </title>
    </head>
    <body link="#0000cc">
      <div id="wrapper">
        <div id="head">
            <div class="head_wrapper">
              <div id="u1">
                <a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻 </a>
                <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
                <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
                <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
                <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
                <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
              </div>
            </div>
        </div>
      </div>
    </body>
    </html>

    python代码:

    from bs4 import BeautifulSoup
    
    file = open('../pachong.html', 'rb')
    html = file.read()
    bs = BeautifulSoup(html, "html.parser")
    # print(bs.prettify())  # 格式化html结构
    print(bs.title)  # 获取title标签
    print(bs.title.name)  # 获取title标签的name
    print(bs.title.string)  # 获取title标签的文本内容
    print(bs.title.get_text())
    # print(bs.head)
    print(bs.div)  # 获取第一个div标签中的所有内容
    print(bs.div["id"])  # 获取第一个div标签的id的值
    print(bs.a)  # 获取第一个a标签
    print(bs.find_all("a"))  # 获取所有的a标签
    print(bs.find(id="u1"))  # 获取id="u1"的标签
    for item in bs.find_all("a"):
        print(item.get("href"))  # 获取所有的a标签,并遍历打印a标签中的href的值
    for item in bs.find_all("a"):
        print(item.string)  # 获取所有的a标签,并遍历打印a标签的文本内容

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

    Tag:

    通俗点讲就是HTML中的一个个标签,例如:

    from bs4 import BeautifulSoup 
    file = open('../pachong.html', 'rb') 
    html = file.read() 
    bs = BeautifulSoup(html,"html.parser") 
    # 获取title标签的所有内容
    print(bs.title) 
    # 获取head标签的所有内容
    print(bs.head) 
    # 获取第一个a标签的所有内容
    print(bs.a) 
    # 类型
    print(type(bs.a))

    tag中重要的属性:name和attributes

    from bs4 import BeautifulSoup 
    file = open('../pachong.html', 'rb') 
    html = file.read() 
    bs = BeautifulSoup(html,"html.parser") 
    # [document] #bs 对象本身比较特殊,它的 name 即为 [document]
    print(bs.name) 
    # head #对于其他内部标签,输出的值便为标签本身的名称
    print(bs.head.name) 
    # 在这里,我们把 a 标签的所有属性打印输出了出来,得到的类型是一个字典。
    print(bs.a.attrs) 
    #还可以利用get方法,传入属性的名称,二者是等价的
    print(bs.a['class']) # 等价 bs.a.get('class')
    # 可以对这些属性和内容等等进行修改
    bs.a['class'] = "newClass"
    print(bs.a) 
    # 还可以对这个属性进行删除
    del bs.a['class'] 
    print(bs.a)

    3、遍历文档树

    3.1、.contents:获取Tag的所有子节点,返回一个list

    # tag的.content 属性可以将tag的子节点以列表的方式输出
    print(bs.head.contents)
    # 用列表索引来获取它的某一个元素
    print(bs.head.contents[1])

    3.2、.children:获取Tag的所有子节点,返回一个生成器

    print(type(bs.head.children))
    for child in bs.head.children:
        print(child)

    3.3、.descendants:获取Tag的所有子孙节点

    3.4、.strings:如果Tag包含多个字符串,即在子孙节点中有内容,可以用此获取,而后进行遍历

    3.5、.stripped_strings:与strings用法一致,只不过可以去除掉那些多余的空白内容

    3.6、.parent:获取Tag的父节点

    3.7、.parents:递归得到父辈元素的所有节点,返回一个生成器

    3.8、.previous_sibling:获取当前Tag的上一个节点,属性通常是字符串或空白,真实结果是当前标签与上一个标签之间的顿号和换行符

    3.9、.next_sibling:获取当前Tag的下一个节点,属性通常是字符串或空白,真是结果是当前标签与下一个标签之间的顿号与换行符

    3.10、.previous_siblings:获取当前Tag的上面所有的兄弟节点,返回一个生成器

    3.11、.next_siblings:获取当前Tag的下面所有的兄弟节点,返回一个生成器

    3.12、.previous_element:获取解析过程中上一个被解析的对象(字符串或tag),可能与previous_sibling相同,但通常是不一样的

    3.13、.next_element:获取解析过程中下一个被解析的对象(字符串或tag),可能与next_sibling相同,但通常是不一样的

    3.14、.previous_elements:返回一个生成器,可以向前访问文档的解析内容

    3.15、.next_elements:返回一个生成器,可以向后访问文档的解析内容

    3.16、.has_attr:判断Tag是否包含属性

    4、搜索文档树

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

    在上面的栗子中我们简单介绍了find_all的使用,接下来介绍一下find_all的更多用法-过滤器。这些过滤器贯穿整个搜索API,过滤器可以被用在tag的name中,节点的属性等。

    (1)name参数:

    字符串过滤:会查找与字符串完全匹配的内容

    a_list = bs.find_all("a")
    print(a_list)

    正则表达式过滤:如果传入的是正则表达式,那么BeautifulSoup4会通过search()来匹配内容

    t_list = bs.find_all(re.compile("a")) 
    for item in t_list: 
       print(item)

    列表:如果传入一个列表,BeautifulSoup4将会与列表中的任一元素匹配到的节点返回

    t_list = bs.find_all(["meta","link"])
    for item in t_list:
        print(item)

    方法:传入一个方法,根据方法来匹配

    def name_is_exists(tag): 
        return tag.has_attr("name") 
    t_list = bs.find_all(name_is_exists) 
    for item in t_list: 
        print(item)

    (2)kwargs参数:

    # 查询id=head的Tag
    t_list = bs.find_all(id="head") 
    print(t_list) # 查询href属性包含ss1.bdstatic.com的Tag t_list = bs.find_all(href=re.compile("http://news.baidu.com")) print(t_list) # 查询所有包含class的Tag(注意:class在Python中属于关键字,所以加_以示区别) t_list = bs.find_all(class_=True) for item in t_list: print(item)

    (3)attrs参数:

    并不是所有的属性都可以使用上面这种方式进行搜索,比如HTML的data-*属性:

    t_list = bs.find_all(data-foo="value")

    如果执行以上这行代码,将会报错。我们可以使用attrs参数,定义一个字典来搜索包含特殊属性的tag:

    t_list = bs.find_all(attrs={"data-foo":"value"})
    for item in t_list:
        print(item)

    (4)text参数:

    通过text参数可以搜索文档中的字符串内容,与name参数的可选值一样,text参数接受 字符串,正则表达式,列表

    t_list = bs.find_all(attrs={"data-foo": "value"}) 
    for item in t_list: 
        print(item) 
    t_list = bs.find_all(text="hao123") 
    for item in t_list: 
        print(item) 
    t_list = bs.find_all(text=["hao123", "地图", "贴吧"]) 
    for item in t_list: 
        print(item) 
    t_list = bs.find_all(text=re.compile("d")) 
    for item in t_list: 
        print(item)

    当我们搜索text中的一些特殊属性时,同样也可以传入一个方法来达到我们的目的:

    def length_is_two(text):
        return text and len(text) == 2
    t_list = bs.find_all(text=length_is_two)
    for item in t_list:
        print(item)

    (5)limit参数:

    可以传入一个limit参数来限制返回的数量,当搜索出的数据量为5,而设置了limit=2时,此时只会返回前2个数据

    t_list = bs.find_all("a",limit=2) 
    for item in t_list: 
        print(item)

    find_all除了上面一些常规的写法,还可以对其进行一些简写:

    # 两者是相等的
    # t_list = bs.find_all("a") => t_list = bs("a")
    t_list = bs("a") # 两者是相等的
    # t_list = bs.a.find_all(text="新闻") => t_list = bs.a(text="新闻")
    t_list = bs.a(text="新闻")

    4.2、find()

    find()将返回符合条件的第一个Tag,有时我们只需要或一个Tag时,我们就可以用到find()方法了。当然了,也可以使用find_all()方法,传入一个limit=1,然后再取出第一个值也是可以的,不过未免繁琐。

    # 返回只有一个结果的列表
    t_list = bs.find_all("title",limit=1) 
    print(t_list) 
    # 返回唯一值
    t = bs.find("title") 
    print(t) 
    # 如果没有找到,则返回None
    t = bs.find("abc") print(t)

    从结果可以看出find_all,尽管传入了limit=1,但是返回值仍然为一个列表,当我们只需要取一个值时,远不如find方法方便。但

    是如果未搜索到值时,将返回一个None

    在上面介绍BeautifulSoup4的时候,我们知道可以通过bs.div来获取第一个div标签,如果我们需要获取第一个div下的第一个div,

    我们可以这样:

    t = bs.div.div
    # 等价于
    t = bs.find("div").find("div")

    5、CSS选择器

    BeautifulSoup支持发部分的CSS选择器,在Tag获取BeautifulSoup对象的.select()方法中传入字符串参数,即可使用CSS选择器的语法找到Tag:

    5.1、通过标签名查找

    print(bs.select('title'))
    print(bs.select('a'))

    5.2、通过类名查找

    print(bs.select('.mnav'))

    5.3、通过id查找

    print(bs.select('#u1'))

    5.4、组合查找

    print(bs.select('div .bri'))

    5.5、属性查找

    print(bs.select('a[class="bri"]'))
    print(bs.select('a[href="http://tieba.baidu.com"]'))

    5.6、直接子标签查找

    t_list = bs.select("head > title")
    print(t_list)

    5.7、兄弟节点标签查找

    t_list = bs.select(".mnav ~ .bri")
    print(t_list)

    5.8、获取内容

    t_list = bs.select("title")
    print(bs.select('title')[0].get_text())
  • 相关阅读:
    P1144 最短路计数 题解 最短路应用题
    C++高精度加减乘除模板
    HDU3746 Teacher YYF 题解 KMP算法
    POJ3080 Blue Jeans 题解 KMP算法
    POJ2185 Milking Grid 题解 KMP算法
    POJ2752 Seek the Name, Seek the Fame 题解 KMP算法
    POJ2406 Power Strings 题解 KMP算法
    HDU2087 剪花布条 题解 KMP算法
    eclipse创建maven项目(详细)
    maven的作用及优势
  • 原文地址:https://www.cnblogs.com/jasmine0627/p/14267366.html
Copyright © 2011-2022 走看看