精华内容
下载资源
问答
  • Python对html解析(BeautifulSoup)

    万次阅读 2020-11-05 16:57:54
    BeautifulSoup支持不同的解析器,比如,对HTML解析,对XML解析,对HTML5解析。一般情况下,我们用的比较多的是 lxml 解析器。 BeautifulSoup安装  BeautifulSoup3 目前已经停止更新,推荐在现在的项目中使用...

    微信搜索:“二十同学” 公众号,欢迎关注一条不一样的成长之路

    BeautifulSoup简介

      BeautifulSoup是一个高效的网页解析库,可以从 HTML 或 XML 文件中提取数据。BeautifulSoup支持不同的解析器,比如,对HTML解析,对XML解析,对HTML5解析。一般情况下,我们用的比较多的是 lxml 解析器。

    BeautifulSoup安装

      BeautifulSoup3 目前已经停止更新,推荐在现在的项目中使用BeautifulSoup4,不过它已经被移植到bs4了。也就是说导入时我们需要 import bs4 。可以利用 pip 或者 easy_install 两种方法来安装。下面采用pip安装。

      pip install beautifulsoup4

      pip install lxml

      建议同时安装"lxml"模块,BeautifulSoup支持Python标准库中的HTML解析器("html.parser"),还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装。

    创建对象

      安装后,创建对象:soup = BeautifulSoup(markup='类html字符串', 'lxml')  # 这里有个坑,"lxml" 解析器会将所有节点名称转为小写!使用 "xml" 解析器则不会转换。所以操作XML用“xml”,操作HTML用“lxml”。

      格式化输出:soup.prettify()

    BeautifulSoup四大对象类型

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

    • BeautifulSoup(文档)
    • Tag(标签)
    • NavigableString(内容)
    • Comment(注释)

    1.BeautifulSoup类型(文档)

      BeautifulSoup对象表示的是一个文档的全部内容:

    print soup.name 
    # [document]

    2.Tag类型(标签)

      即HTML的整个标签,如获取<title>标签:

    print soup.title
    #<title>The Dormouse's story</title>

      Tag有两个重要属性:name,attrs。

    name

      即HTML的标签名称:

    print soup.name
    #[document]
    print soup.head.name
    #head

    attrs

      即HTML的标签属性字典:

    print soup.p.attrs
    #{'class': ['title'], 'name': 'dromouse'}

      如果想要单独获取某个属性:

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

    3.NavigableString类型(内容)

      既然我们已经得到了整个标签,那么问题来了,我们要想获取标签内部的文字内容怎么办呢?很简单,用 string 即可:

    print soup.p.string
    #The Dormouse's story

    4.Comment类型(注释)

      HTML的注释内容,注意的是,不包含注释符号。我们首先判断它的类型,是否为 Comment 类型,然后再进行其他操作,如打印输出:

    if type(soup.a.string)==bs4.element.Comment:
        print soup.a.string
    #<!-- Elsie -->

    遍历文档树

    1.子节点

    contents

      获取所有子节点,返回列表:

    print soup.head.contents 
    #[<title>The Dormouse's story</title>]

    children

      获取所有子节点,返回列表生成器:

    print soup.head.children
    #<listiterator object at 0x7f71457f5710>
    
    ## 需要遍历
    for child in  soup.body.children:
        print child
    
    ## 结果
    <p class="title" name="dromouse"><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>;
    and they lived at the bottom of a well.</p>
    
    
    <p class="story">...</p>

    2.节点内容

    string

      返回单个文本内容。如果一个标签里面没有标签了,那么 string 就会返回标签里面的内容。如果标签里面只有唯一的一个标签了,那么 string 也会返回最里面的内容。如果tag包含了多个子节点,tag就无法确定,string 方法应该调用哪个子节点的内容,string 的输出结果是 None。例如:

    print soup.head.string
    print soup.title.string
    #The Dormouse's story
    #The Dormouse's storyprint soup.html.string# None

    strings

      返回多个文本内容,且包含空行和空格。

    stripped_strings

      返回多个文本内容,且不包含空行和空格:

    for string in soup.stripped_strings:
        print(repr(string))
        # u"The Dormouse's story"
        # u"The Dormouse's story"
        # u'Once upon a time there were three little sisters; and their names were'
        # u'Elsie'
        # u','
        # u'Lacie'
        # u'and'
        # u'Tillie'
        # u';\nand they lived at the bottom of a well.'
        # u'...'

    get_text()方法

      返回当前节点和子节点的文本内容。

    from bs4 import BeautifulSoup
    
    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="sister1" id="link1">Elsie</a>,
            <a href="http://example.com/lacie" class="sister2" id="link2">Lacie</a> and
            <a href="http://example.com/tillie" class="sister3" id="link3">Tillie</a>;
            and they lived at the bottom of a well.
        </p>
        <p class="story">...</p>
    </body>
    </html>
    """
    
    soup = BeautifulSoup(markup=html_doc,features='lxml')
    
    node_p_text=soup.find('p',class_='story').get_text()    # 注意class_带下划线
    print(node_p_text)
    
    # 结果
    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.

    3.父节点

    parent

      返回某节点的直接父节点:

    p = soup.p
    print p.parent.name
    #body

    parents

      返回某节点的所有父辈及以上辈的节点:

    content = soup.head.title.string
    for parent in  content.parents:
        print parent.name
    
    ## 结果
    title
    head
    html
    [document]

    4.兄弟节点

    next_sibling

      next_sibling 属性获取该节点的下一个兄弟节点,结果通常是字符串或空白,因为空白或者换行也可以被视作一个节点。

    previous_sibling

      previous_sibling 属性获取该节点的上一个兄弟节点。

    print soup.p.next_sibling
    #       实际该处为空白
    print soup.p.prev_sibling
    #None   没有前一个兄弟节点,返回 None
    print soup.p.next_sibling.next_sibling
    #<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>;
    #and they lived at the bottom of a well.</p>
    #下一个节点的下一个兄弟节点是我们可以看到的节点

    next_siblings、previous_siblings

      迭代获取全部兄弟节点。

    5.前后节点

    next_element、previous_element

      不是针对于兄弟节点,而是在于所有节点,不分层次的前一个和后一个节点。

    next_elements、previous_elements

      迭代获取所有前和后节点。

    搜索文档树

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

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

    参数说明

    name参数

      name参数很强大,可以传多种方式的参数,查找所有名字为 name 的tag,字符串对象会被自动忽略掉。

    (a)传标签名  最简单的过滤器是标签名。在搜索方法中传入一个标签名参数,BeautifulSoup会查找与标签名完整匹配的内容,下面的例子用于查找文档中所有的<a>标签:

    print 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>]

      返回结果列表中的元素仍然是BeautifulSoup对象。

    (b)传正则表达式

      如果传入正则表达式作为参数,BeautifulSoup会通过正则表达式的 match() 来匹配内容。下面例子中找出所有以b开头的标签,这表示<body>和<b>标签都应该被找到:

    import re
    for tag in soup.find_all(re.compile("^b")):
        print(tag.name)
    # body
    # b

    (c)传列表

      如果传入列表参数,BeautifulSoup会将与列表中任一元素匹配的内容返回。下面代码找到文档中所有<a>标签和<b>标签:

    soup.find_all(["a", "b"])
    # [<b>The Dormouse's story</b>,
    #  <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>]

    (d)传True

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

    for tag in soup.find_all(True):
        print(tag.name)
    # html
    # head
    # title
    # body
    # p
    # b
    # p
    # a
    # a

    (e)传函数

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

    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>]

    keyword参数  注意的是,如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,BeautifulSoup会搜索每个tag的”id”属性:

    soup.find_all(id='link2')
    # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

      如果传入 href 参数,Beautiful Soup会搜索每个tag的"href"属性:

    soup.find_all(href=re.compile("elsie"))
    # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

      使用多个指定名字的参数可以同时过滤tag的多个属性:

    soup.find_all(href=re.compile("elsie"), id='link1')
    # [<a class="sister" href="http://example.com/elsie" id="link1">three</a>]

      在这里我们想用 class 过滤,不过 class 是 python 的关键词,这怎么办?加个下划线就可以:

    soup.find_all("a", class_="sister")
    # [<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>]

    attrs参数

      有些tag属性在搜索不能使用,比如HTML5中的 " data-* " 自定义属性:

    data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')
    data_soup.find_all(data-foo="value")
    # SyntaxError: keyword can't be an expression
    
    ## 但是可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag
    data_soup.find_all(attrs={"data-foo": "value"})
    # [<div data-foo="value">foo!</div>]

    text参数

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

    soup.find_all(text="Elsie")
    # [u'Elsie']
    
    soup.find_all(text=["Tillie", "Elsie", "Lacie"])
    # [u'Elsie', u'Lacie', u'Tillie']
    
    soup.find_all(text=re.compile("Dormouse"))  # 模糊查找
    [u"The Dormouse's story", u"The Dormouse's story"]

    limit参数

      find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢。如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量。效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果。

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

    recursive参数

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

    soup.html.find_all("title")
    # [<title>The Dormouse's story</title>]
    
    soup.html.find_all("title", recursive=False)
    # []

    2.find( name , attrs , recursive , text , **kwargs )

      它与 find_all() 方法唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果。

    3.find_parents() 和 find_parent()

      find_all() 和 find() 只搜索当前节点的所有子节点,孙子节点等。find_parents() 和 find_parent() 用来搜索当前节点的父辈节点,搜索方法与普通tag的搜索方法相同,搜索文档搜索文档包含的内容。

    4.find_next_siblings() 和 find_next_sibling()  

      这2个方法通过 .next_siblings 属性对当 tag 的所有后面解析的兄弟 tag 节点进行迭代, find_next_siblings() 方法返回所有符合条件的后面的兄弟节点,find_next_sibling() 只返回符合条件的后面的第一个tag节点。

    5.find_previous_siblings() 和 find_previous_sibling()

      这2个方法通过 .previous_siblings 属性对当前 tag 的前面解析的兄弟 tag 节点进行迭代, find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点,find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点。

    6.find_all_next() 和 find_next()

      这2个方法通过 .next_elements 属性对当前 tag 的之后的 tag 和字符串进行迭代, find_all_next() 方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点。

    7.find_all_previous() 和 find_previous()

      这2个方法通过 .previous_elements 属性对当前节点前面的 tag 和字符串进行迭代,find_all_previous() 方法返回所有符合条件的节点, find_previous()方法返回第一个符合条件的节点。

     CSS选择器

       我们在写 CSS 时,标签名不加任何修饰,类名前加点,id名前加 #,在这里我们也可以利用类似的方法来筛选元素,用到的方法是 soup.select(),返回类型是 list。

    通过标签名查找

    print soup.select('title') 
    #[<title>The Dormouse's story</title>]
    
    print soup.select('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>]
    
    print soup.select('b')
    #[<b>The Dormouse's story</b>]

    通过类名查找

    print soup.select('.sister')
    #[<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>]

    通过 id 名查找

    print soup.select('#link1')
    #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

    组合查找

      组合查找即和写 class 文件时,标签名与类名、id名进行的组合原理是一样的,例如查找 p 标签中,id 等于 link1的内容,二者需要用空格分开。

    print soup.select('p #link1')
    #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

      直接子标签查找:

    print soup.select("head > title")
    #[<title>The Dormouse's story</title>]

    属性查找

      查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。

    print soup.select('a[class="sister"]')
    #[<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>]
    
    print soup.select('a[href="http://example.com/elsie"]')
    #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

      同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开,同一节点的不加空格:

    print soup.select('p a[href="http://example.com/elsie"]')
    #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

      以上的 select 方法返回的结果都是列表形式,可以遍历形式输出,然后用 string或get_text() 方法来获取它的内容:

    soup = BeautifulSoup(html, 'lxml')
    print type(soup.select('title'))
    print soup.select('title')[0].get_text()
    
    for title in soup.select('title'):
        print title.get_text()

    修改文档树

    1.修改.string

    给Tag的 .string 属性赋值,就相当于用当前的内容替代了原来的内容。(如果当前的Tag包含了其它tag,那么给它的 .string 属性赋值会覆盖掉原有的所有内容包括子Tag)。

    如,soup.find('title').string = '新标题'

    2.append()

    Tag.append() 方法向Tag中添加子内容,与Python的列表的 append() 方法用法相同。

    如,soup.find('p').append('段落内容')

    3.new_tag()

    创建一个Tag最好的方法是调用工厂方法 BeautifulSoup.new_tag()。

    如,soup.find('p').append(soup.new_tag('a', href='http://www.baidu.com'))

    4.insert()、insert_before() 和 insert_after()

    把元素插入到指定的位置。

    如,soup.find('p').insert_after(soup.new_tag('a', href='http://www.baidu.com'))

    5.decompose()

    Tag.decompose() 方法将当前节点完全移除。

    6.clear()

    Tag.clear() 方法清空当前节点的内容

    展开全文
  • HTML解析-Xpath

    千次阅读 2019-08-20 10:20:43
    HTML解析-Xpath 文章目录HTML解析-XpathXPath节点lxml HTML的内容返回给浏览器,浏览器就会解析它,并对它渲染。 HTML超文本表示语言,设计的初衷就是为了超越普通文本,让文本表现力更强。 XML扩展标记语言,...

    HTML解析-Xpath


    HTML的内容返回给浏览器,浏览器就会解析它,并对它渲染。

    HTML超文本表示语言,设计的初衷就是为了超越普通文本,让文本表现力更强。
    XML扩展标记语言,不是为了替代HTML,而是觉得HTML的设计中包含了过多的格式,承担了一部分数据之外的任务,所以才设计了XML只用来描述数据。

    HTML和XML都有结构,使用标记形成树型的嵌套结构。DOM(Document Object Model)来解析这种嵌套树型结构,浏览器往往都提供了对DOM操作的API,可以用面向对象的方式来操作DOM。

    XPath

    • http://www.w3school.com.cn/xpath/index.asp中文教程

    • XPath是一门在XML文档中查找信息的语言。XPath可用来在XML文档中对元素和属性进行遍历。

    • 测试工具:XMLQuire win7+需要.net框架4.0-4.5。

    • 测试XML、XPath

      1. 测试文档

        <?xml version="1.0" encoding="utf-8"?>
        <bookstore>
        <book id="bk101">
            <author>Gambardella, Matthew</author>
            <title>XML Developer's Guide</title>
            <genre>Computer</genre>
            <price>44.95</price>
            <publish_date>2000-10-01</publish_date>
            <description>An in-depth look at creating applications 
            with XML.</description>
        </book>
        <book id="bk102" class="bookinfo even">
            <author>Ralls, Kim</author>
            <title>Midnight Rain</title>
            <genre>Fantasy</genre>
            <price>5.95</price>
            <publish_date>2000-12-16</publish_date>
            <description>A former architect battles corporate zombies, 
            an evil sorceress, and her own childhood to become queen 
            of the world.</description>
        </book>
        <book id="bk103">
            <author>Corets, Eva</author>
            <title>Maeve Ascendant</title>
            <genre>Fantasy</genre>
            <price>5.95</price>
            <publish_date>2000-11-17</publish_date>
            <description>After the collapse of a nanotechnology 
            society in England, the young survivors lay the 
            foundation for a new society.</description>
        </book>
        <book id="bk104">
            <author>Corets, Eva</author>
            <title>Oberon's Legacy</title>
            <genre>Fantasy</genre>
            <price>5.95</price>
            <publish_date>2001-03-10</publish_date>
            <description>In post-apocalypse England, the mysterious 
            agent known only as Oberon helps to create a new life 
            for the inhabitants of London. Sequel to Maeve 
            Ascendant.</description>
        </book>
        </bookstore>
        
      2. 测试工具:XMLQuire win7+需要.NET框架4.0-4.5。
        xpath_001

    节点

    • 在XPath中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。

      1. /根节点
      2. <bookstore>元素节点
      3. <author>Corets,Eva</author>元素节点。
      4. id="bk104"是属性节点,id是元素节点book的属性
    • 节点之间的嵌套形成父子(parent,children)关系

    • 具有统一个父结点的不同节点是兄弟(sibling)关系

    • 节点选择

    操作符或表达式 含义
    / 从根节点开始找
    // 从当前节点开始的任意层找
    . 当前节点
    .. 当前结点的父节点
    @ 选择属性
    节点名 选取所有这个节点名的节点
    * 匹配任意元素节点
    @* 匹配任意属性节点
    node() 匹配任意类型的节点
    text() 匹配text类型节点
    • 谓语(Predicates)
    1. 谓语用来查找某个特定的节点或者包含某个指定的值的节点。
    2. 谓语被嵌在方括号中
    3. 谓语就是查询的条件。
    4. 即在路径选择时,在中括号内指定查询条件。
    • XPath轴(Axes)
    1. 轴的意思是相对于当前结点的节点集
    轴名称 结果
    ancestor 选取当前结点的所有先辈(父、祖父等)
    ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身
    attribute 选取当前节点的所有属性。@id等价于attribute::id
    child 选取当前节点的所有子元素,title等价于child:title
    descendant 选取当前节点的所有后代元素(子、孙等)
    descendant-or-self 选取当前节点的所有后代运算(子、孙等)以及当前节点本身
    following 选取文档中当前节点的结束标签之后的所有结点
    namespace 选取当前节点的所有命名空间节点
    parent 选取当前节点的父节点
    preceding 选取当前节点的父节点
    preceding-sibling 选取当前节点之前的所有同级节点
    self 选取当前节点。等驾驭self::node()
    • 步Step
    1. 步的语法轴名称:节点测试[谓语]
    例子 结果
    child::book 选取所有属于当前节点的只元素的book节点
    attribute::lang 选取当前节点的lang属性
    child::* 选取当前节点的所有只元素
    attribute::* 选取当前节点的所有属性
    child::text() 选取当前节点的所有文本子节点
    child::node() 选取当前节点的所有子节点
    descendant::book 选取当前节点的所有book后代
    ancestor:book 选择当前节点的所有book先辈
    ancestor-or-self::book 选取当前节点的所有book先辈以及当前节点(如果此节点是book节点)
    child::*/child::price 选取当前节点的所有price孙节点

    xpath_002

    xpath_003

    • XPATH示例
    1. 以斜杠开始的称为绝对路径,表示从根开始。
    2. 不以斜杠开始的称为相对路径,一般都是依照当前节点来计算。当前节点在上下文环境中,当前节点很可能已经补是根节点了。
    3. 一般为了方便,往往xml如果层次很深,都会使用//来查找节点。
    路径表达式 含义
    title 选取当前节点下所有title子节点
    /book 从根节点找子节点是book的,找不到
    book/title 当前节点下所有子节点book下的title节点
    //title 从根节点向下找任意层中title的结点
    book//title 当前节点下所有book子节点下任意层次的title节点
    //@id 任意层次下含有id的属性,取回的是属性
    //book[@id] 任意层次下含有id属性的book节点
    //*[@id] 任意层下含有id属性的节点
    //book[@id="bk102"] 任意层次下book节点,且含有id属性为bk102的节点。
    /bookstore/book[1] 根节点bookstore下第一个book节点,从1开始
    /bookstore/book[1]/@id 根节点bookstore下的第一个book节点的id属性
    /bookstore/book[last()-1] 根节点bookstore下倒数第二个book节点,
    函数last()返回最后一个元素索引
    /bookstore/* 匹配根节点bookstore的所有子节点,不递归
    //* 匹配所有子孙节点
    //*[@*] 匹配所有有属性的节点
    //book/title | //price 匹配任意层下的book下节点是title节点,或者任意层下的price
    //book[position()=2] 匹配book节点,取第二个
    //book[position()<last()-1] 匹配book节点,取位置小于倒数第二个
    //book[price>40] 匹配book节点,取节点值大于40的book节点
    //book[2]/node() 匹配位置为2的book节点下的所有类型的节点
    //book[1]/text() 匹配第一个book节点下的所有文本子节点
    //book[1]/text() 匹配第一个book节点下的所有文本节点
    //*[local-name()="book"] 匹配所有节点且不带限定名的节点名称为book的所有节点。
    local-name函数取不带限定名的名称。相当于指定标签元素为…的节点
    下面这三种表达式等价
    //book[price<6]/price
    //book/price[text()<6]
    //book/child::node()[local-name()="price" and text()<6]
    获取book节点下的price节点,且price中内容小于6的节点
    //book//*[self::title or self::price]
    等价于//book//title | //book/price
    也等价于//book//*[local-name()="title" or local-name()="price"]
    所有book节点下子孙节点,且这些节点是title或者price。
    //*[@class] 所有有class属性的节点
    //*[@class="bookinfo even"] 所有属性为“bookinfo even”的节点
    //*[contains(@class,'even') 获取所有属性class中包含even字符串的节点
    //*[contains(local-name(),'book') 标签名包含book的节点
    • 函数总结
    函数 含义
    local-name() 获取不带限定名的名称。相当于指定标签元素
    text() 获取标签之间的文本内容
    node() 所有节点。
    contains(@class,str) 包含
    starts-with(local-name(),"book") 以book开头
    last() 最后一个元素索引
    position() 元素索引

    lxml

    • lxml是Python下功能丰富的XML、HTML解析库,性能非常好,是对libxml2和libxslt的封装。
    • 最新版本支持Python 2.6+,python3支持3.6.
    1. 在CentOS编译安装需要

    #yum install libxml2-devel libxslt-devel

    from lxml import etree
    
    # 使用etree构建HTML
    root = etree.Element("html")
    print(type(root))
    print(root.tag)
    
    body = etree.Element("body")
    root.append(body)
    print(etree.tostring(root))
    
    #增加子节点
    sub = etree.SubElement(body,"child1")
    print(type(sub))
    sub = etree.SubElement(body,"child2").append(etree.Element("child21"))
    html = etree.tostring(root,pretty_print=True).decode()
    print(html)
    print("- "*30)
    
    r = etree.HTML(html) #返回根节点
    print(r.tag)
    print(r.xpath("//*[contains(local-name(),'child')]"))
    

    xpath_004

    1. etree还提供了2个有用的函数
    2. etree.HTML(text)解析HTML文档,返回根节点
    3. anode.xpath(‘xpath路径’)对节点使用xpath语法
    • 练习:爬取“口碑榜”
      1. 从豆瓣电影中获取"本周口碑榜"
    from lxml import etree
    import requests
    
    url = "https://movie.douban.com/"
    ua = "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN) AppleWebKit/537.36 (KHTML, like Gecko) Version/5.0.1 Safari/537.36"
    
    with requests.get(url,headers={"User-agent":ua}) as response:
        if response.status_code==200:
            content = response.text #html内容
            html = etree.HTML(content) #分析html,返回DOM根节点
            titles = html.xpath("//div[@class='billboard-bd']//tr/td/a/text()") #返回文本列表
            for i in titles: #豆瓣电影之本周排行榜
                print(i)
        else:
            print("访问错误")
    

    xpath_005

    展开全文
  • QT html解析

    千次阅读 2016-03-11 21:54:42
    QT是支持html解析的。 什么意思呢,一段代码就明白了。 QLabel *label=newQLabel("hello,world!");  label->show(); 运行后的结果看看是什么样子的: 当然,不止是QLabel这个类,其他的widget也是支持这...

    QT是支持html解析的。

    什么意思呢,一段代码就明白了。

    QLabel *label=newQLabel("<h2><fontcolor='red'>hello</font>,world!</h2>");

        label->show();

    运行后的结果看看是什么样子的:


    当然,不止是QLabel这个类,其他的widget也是支持这中美化方式的。

    展开全文
  • 【Python】 html解析BeautifulSoup

    千次阅读 2017-06-09 17:15:48
    转自:... 【Python】 html解析BeautifulSoup BeautifulSoup  bs是个html解析模块,常用来做爬虫?  ■ 安装  BeautifulSoup可以通过pip来安装,用pip install beautifulsoup4 即

    转自:http://www.cnblogs.com/franknihao/p/6542460.html

    【Python】 html解析BeautifulSoup

    BeautifulSoup

      bs是个html解析模块,常用来做爬虫?

      ■  安装

      BeautifulSoup可以通过pip来安装,用pip install beautifulsoup4 即可。但是仅仅这样安装的bs,其默认的html解析器是python自带的HTMLParser模块,性能不是很好。可以考虑安装性能更加好的lxml和html5lib模块:pip install html5lib

      

      ■  基本用法

       BeautifulSoup有官方文档,可以查阅

      ① 建立BeautifulSoup对象,它是基于一个html字符串或者一个文件

    复制代码
    from bs4 import BeautifulSoup
    soup = BeautifulSoup("...一串html")
    #或者
    soup = BeautifulSoup(open("文件路径","r"))
    
    print soup.prettify()    #可以美化这段html并打印出来
    复制代码

       ②  四类对象

       bs将一个html抽象成一个树形结构,每个节点都是一个python里的对象。共分成了四种对象。

       ●  Tag类对象

        即html中的标签,BeautifulSoup对象(以上面代码中的soup为例)可以直接在后面接上某种标签的名称,得到的对象是该种标签在这段html中的第一个实例。

        比如对于print soup.h1 >>> <h1 class="...">...</h1>  (bs里的html对象是可打印的,打印出来就是html原文)

        每个Tag类对象都有两个属性,name和attrs。

        name就是标签的名字,而attrs是个字典,里面记录了所有这个tag的属性值。比如有tag是<h1 class="space-seo space-meta" name="testname">HELLO</h1>

        其name就是u'h1',而attrs是{u'class':[u'space-seo',u'space-meta'],u'name':u'testname'}  //注意区别tag对象的name属性和写在attrs里面的name属性的区别,另外所有被存到变量里的html内容全部都变成了unicode对象。在print的时候可以指定encode,默认encode是utf-8。还有,所有class属性都默认都被解析成一个列表,即便只有一个class值,也会成为[u'class_value']

        当然,在定位到Tag对象之后可以获取查看其属性值,另一方面,也可以对其属性值等进行修改,修改完了之后就是存在内存中的这个变量里面的,最终可以输出成文件的形式。

       ●  String对象  //selenium用的是text来指代标签内部的文本内容,而bs用的是string。而且对于<div>这种本身不带文本带后辈节点可能带文本的标签两者意义不同。selenium中的.text会带出来所有后辈节点中的文本,而bs中的这个.string返回的是None

        String对象用于代表每个元素所含的文字部分,在标签后面加上.string即可调用

        print soup.h1.string >>> HELLO

        注意,某个Tag对象的子节点以及子节点里面的内容都不算进string,当一个元素(比如<div>这种)里面只有子节点,本身没有文字的话,得到的就是None。

        ●  BeautifulSoup对象

        指代整个文档的对象。可以视为是<html>的对象。其实之前创建的BeautifulSoup对象soup,就是指代整个html文档

        ●  comment对象

        用于代表某个元素内的注释

    ■  遍历文件树

        除了上面提到的一些基本属性,Tag对象(包括BeautifulSoup对象)都含有以下属性:

        Tag.contents  将某个Tag的各个子节点(不包括孙和孙以下节点)按照列表的方式输出

        Tag.children  返回一个上述列表的迭代器,也只有子节点(没有孙和孙以下节点)

        Tag.descendants  返回一个迭代器,内容是所有后辈节点

        Tag.strings  返回Tag中所有的文字部分的生成器,保留换行,制表符等空格。相当于是prettify之后去掉所有html标签的文本状态。

        Tag.stripped_strings  和上一项相比,再去掉所有空白字符,只保留有实际字符的文本部分。这两个方法常用于对被分析网页文本的搜索和处理。

     

        Tag.parent  父节点

        Tag.parents  长辈节点的迭代器

     

        Tag.next_sibling  下一个同辈节点(如果没有同辈就返回None,下同)

        Tag.previous_sibling  上一个同辈节点

        Tag.next_sibilings  之后所有同辈节点的迭代器

        Tag.previous_sibilings  之前所有同辈节点的迭代器

        //关于同辈节点有一个坑。。在看起来比较美观的HTML文档中,总是有很多换行符合制表符的。而在BS中如果要调用一个同辈节点,那么这些空白的文本节点也都会被算进去。比如:

     

    复制代码
    #<p><span>one</span><span id="main">two</span></p>
    print soup.find(name="span",attrs={"id":"main"}).previous_sibling
    #得到的是<span>one</span>
    
    #如果处理的是这样一段HTML:
    #<p>
    #    <span>one</span>
    #    <span id="main">two</span>
    #</p>
    print repr(soup.find(name="span",attrs={"id":"main"}).previous_sibling)
    #得到的是"\n\t"因为在第一个span之前有一段空白文本被当做一个节点了。
    复制代码

     

     

     

        然而在通过这个span.parent寻找p或者是通过p.children寻找span的时候,这些空白文本节点都不会被算进去。所以只有在引用同辈节点的时候要注意。

        

        Tag.next_element  下一个元素,包括string对象,子节点,同辈分节点在内,无视辈分的下一个

        Tag.previous_element  上一个元素,说明同上

        Tag.next_elements  next_element的迭代器

        Tag.previous_elements  previous_element的迭代器

        

      ■  检索文件树方法

        ●  Tag.find_all(name,attr,recursive,text,**kwargs) 方法。功能是检索Tag内所有后辈节点,并判断是否符合某种条件,最后返回一个列表

          1.  name参数

          name参数可以直接写Tag.name。比如find_all("p"),find_all("div")等

          也可以写正则表达式(re.compile之后的对象)。比如find_all(re.compile("^b"))

          也可以写列表,比如find_all(['a','p'])

          甚至可以写一个函数对象,这时就要自己定义这个函数了。这个函数要接收一个Tag对象来作为参数,并最终返回True或者False来告诉find_all这个对象该不该被find进去

          2.  attr参数

          attr参数可以指定一个字典的形式来过滤,比如find_all(attrs={'id':'testid'})就是找到所有id是testid的元素

          3.  text参数

          用于搜索字串内容。也可以支持name参数中那几种写的形式。注意,返回的不是对象的列表,而是文本的列表。当name和text的参数同时出现的话,text会作为name的一个附加条件,返回的还是带标签的列表。

          4.  recursive参数

          默认是True,可改成False放弃递归进子辈以下子节点。只检索第一级的子节点。

          5.  limit参数

          有时候文档太大了,检索所有元素很费时间,limit可以指定一个数值,当检索找到了这个数量的目标之后就停止检索

        

         ●  Tag.find方法:参数和find_all一致,只不过其返回的不是一个列表,而是找到第一个就返回了。

     

         ●  Tag.find_parents    Tag.find_parent

          Tag.find_next_sibilings    Tag.find_next_sibiling

          Tag.find_previous_sibilings    Tag.find_previous_sibiling

          Tag.find_all_next    Tag.find_next

          Tag.find_all_previous  Tag.find_previous

          以上所有方法,每行前一个和后一个的关系就是find_all和find的关系。而每一行相当于是为检索指定了一个大致的范围。比如说find_all和find是在所有后辈节点中检索的话,那么find_parents和find_parent就是在所有长辈节点中寻找,find_next_sibilings和find_next_sibiling就是在所有后面的同辈节点中寻找等等

        

         ●  Tag.select("selector")  可以借助select方法来确定一个或多个特定的元素,默认查找全部符合的元素并返回一个列表。selector的语法就是jQuery里面selector的语法。这个方法还是比较实用的。与之相对的有select_one方法,只返回第一个查找到的元素。

     

    总的来说,不管是通过一个节点,遍历文件树的方法来找到想要获得的节点对象,还是通过检索方法来定位一个节点对象,都是寻找对象的一种方法。很难说哪种最好哪种不好,应该要灵活运用。

    展开全文
  • HTML 解析

    千次阅读 2009-08-04 17:11:00
    市面上有很多XML 解析器 ,比如 SAX JDOM DOM DOM4J 等等。...HTML解析器的作用就是容错率高比如如果...下面我就介绍种HTML解析器: cyberneko是一个HTML解析器,它可以将HTML文件解析成w3c的Document对象。Dom4J则支持通
  • Html Agility Pack (HAP):c# HTML 解析利器

    千次阅读 2017-12-17 18:50:57
    【爬虫】系列文章目录Html Agility Pack (HAP)是一个敏捷的HTML解析器,它构建了一个读/写DOM,并且支持普通的XPATH或者XSLT(实际上你不需要理解XPATH或者XSLT来使用它,不用担心)。这是一个.NET代码库,允许您...
  • Android Jsoup:实现HTML解析和Epub解析

    千次阅读 2015-11-04 23:42:29
    概述jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。jsoup的主要功能如下: 从一个URL,文件或字符...
  • 爬虫踩坑系列——etree.HTML解析异常

    万次阅读 2019-08-13 15:02:11
    在这里,为大家分享一个关于etree.HTML解析异常的问题。 1.问题描述: 爬虫过程中,一般会使用requests.get()方法获取一个网页上的HTML内容,然后通过lxml库中的etree.HTML来解析这个网页的结构,最后通过xpath获取...
  • 一个犀利的 HTML 解析器 —— Less.Html

    万次阅读 2017-06-19 13:51:50
    我写了这个解析器之后才知道,原来 C# 写的 html 解析器有很多。但是因为我没有参照别人的做法,Less.Html 有一个特点,就是它的用法是最接近 jQuery 的。我刻意模仿了 jQuery。比如我写的示例一:123456789var q = ...
  • 通过html解析网页数据

    千次阅读 2016-07-28 14:30:34
    这个包叫Jsoup包,jsoup是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。 jar包(点击下载) 中文api文档(点击查看) 接下就来通过我这个项目来说明一下如何解析html 1.分析相应的html代码。 我...
  • python网络爬虫-复杂HTML解析

    万次阅读 2017-09-15 10:54:36
    复杂HTML解析,通过BeautifulSoup的find和findAll来进行复杂界面的解析,使用css的一些属性字段来进行数据定位
  • webkit html 解析流程

    千次阅读 2012-10-30 14:53:13
    语言的解析一般分为词法分析(lexical analysis)和语法分析(Syntax analysis)两个阶段,WebKit中的html解析也不例外,本文主要讨论词法分析。 词法分析的任务是对输入字节流进行逐字扫描,根据构词规则识别单词...
  • HTML解析器的工作是将html标识解析为解析树。 HTML文法定义(The HTML grammar definition) W3C组织制定规范定义了HTML的词汇表和语法。 非上下文无关文法(Not a context free grammar) 正如在解析简介中提到...
  • 引用: ... 介绍了两种不错的HTML解析器的方法。 第一种方法:HTML正则表达式的方法。  参见:http://www.cnblogs.com/gaoweipeng/archive/2009/09/02/1558279.html/  或者直
  • HTML解析神器--HtmlAgilityPack

    千次阅读 2017-03-30 13:27:56
    Html Agility Pack是codeplex里的一款开源库(http://htmlagilitypack.codeplex.com/),是一个灵活的html解析器,支持通过简单XPATH 或 XSLT来读和写DOM,最新版本已经支持LINQ。对开发网络爬虫,网络数据挖掘等...
  • HTML解析器的任务是将HTML标记解析成解析树。 HTML的词汇和语法在W3C规范中进行了定义。 HTML的定义采用了DTD(DocumentType Definition,文档类型定义)。 解析树是由DOM(Document Object Model)元素和属性节点...
  • BeautifulSoup中各种html解析器的比较及使用 转载:https://blog.csdn.net/winterto1990/article/details/47806175 Beautiful Soup解析器比较 ·Beautiful Soup支持各种html解析器,包括python自带的标准库,还有...
  • html解析器对比

    千次阅读 2019-11-19 15:18:26
  • jsoup 是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
  • HTML解析原理

    千次阅读 2017-09-16 21:13:45
    HTML文档尽早指定字符编码,可以让浏览器立刻开始执行脚本。 细节 HTML文档是作为带有字符编码信息的字节流序列在互联网中传送的。字符编码信息可以在随文档发送的HTTP响应头信息中指定,也可以在文档的 HTML...
  • 基于java平台的HTML解析工具,针对HTML字符串,URL地址。功能 1. URL基于网络解析HTML 2. HTML字符串解析 3. 类DOM或CSS选择器解析 4. 解析Body片段字符串、文件、网络解析、DOM树解析、选择器解析:package...
  • 抓取网页数据并解析、Jsoup、
  • webkit关键代码浏览——HTML解析

    千次阅读 2014-02-19 15:05:19
    基础概念就不多说了,直接进入正题,HTML解析这部分我主要关注了6点:1. 词法解析 2. 语法解析 3. 容错机制 4. DOM树构建 5. Render树构建 6. 查看DOM树和Render树
  • HtmlCxx是一款简洁的,非验证式的,用C++编写的css1和html解析器。和其他的几款Html解析器相比,它具有以下的几个特点: 使用由KasperPeeters编写的强大的tree.h库文件,可以实现类似STL的DOM树遍历和导航。 可以...
  • 一个最简单的爬虫-HTML解析

    千次阅读 2017-11-25 17:42:19
    # HTML解析器 import re from bs4 import BeautifulSoup import urllib.parse class HtmlParser(object): def parse(self, page_url, html_cont): if page_url is None or html_cont is None: r
  • Android Html解析

    万次阅读 2016-05-22 18:05:20
    Android SpannableString浅析中我们采用html实现了文本处理的效果。当时设置部分的代码如下:private void setText() { String originText = "#重磅消息#近日谷歌放出Android N的第二个开发者预览版(Developer ...
  • java世界中几种html解析的工具

    万次阅读 2016-11-09 17:27:33
    Jsoup是一个集强大和便利于一体的HTML解析工具。它方便的地方是,可以用于支持用jquery中css selector的方式选取元素,这对于熟悉js的开发者来说基本没有学习成本。 String content = "blabla"; Document doc = ...
  • Python3 HTML 解析

    千次阅读 2011-11-22 14:17:31
    作为爬虫比较重要的一部分HTML解析器: Python3 自己有一个,使用了一下,还不是很好用 第三方的有:  目前还不支持Python3 , Python3 的资料还不是很多  BeautifulSoup -- 支持版本2.x 很不错,我不想退版本...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 72,809
精华内容 29,123
关键字:

html解析