Python爬虫网页,解析工具lxml.html(二)

作者: 一墨编程学习 | 来源:发表于2019-04-29 22:11 被阅读1次

    【前情回顾】如何灵活的解析网页,提取我们想要的数据,是我们写爬虫时非常关心和需要解决的问题。

    从Python的众多的可利用工具中,我们选择了lxml的,它的好我们知道,它的妙待我们探讨。前面我们已经从HTML字符串转换成的HtmlElement对象,接下来我们就探讨该如何操作这个的HtmlElement对象。

    如果你依然在编程的世界里迷茫,不知道自己的未来规划,可以加入我们的Python学习扣qun:784758214,看看前辈们是如何学习的!交流经验!
    自己是一名高级python开发工程师,从基础的python脚本到web开发、爬虫、django、人工智能、数据挖掘等,零基础到项目实战的资料都有整理。
    送给每一位python的小伙伴!分享一些学习的方法和需要注意的小细节,这里是python学习者聚集地

    点击:python技术分享

    lxml.html的HtmlElement对象的各种属性和方法

    这个的HtmlElement对象有各种方法,我们重点讨论跟解析网页相关的函数,而修改这个对象的方法若与提取内容相关也一并介绍,介绍过程结合下面这段HTML代码以便更好说明问题:

    <div class="post" id="123">
        <p class="para">abc<a href="/to-go">link</a></p>
    </div>
    
    

    .attrib属性和.get()方法

    前者是html tag的属性集合,以字典表示;后者是取得某个属性的值,相当于字典的.get()方法。看示例:

    In [35]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
    
    In [37]: doc.attrib
    Out[37]: {'class': 'post', 'id': '123'}
    
    In [38]: doc.get('class')
    Out[38]: 'post'
    
    

    .drop_tag()方法

    移除该html标签,但保留它的子节点和文本并合并到该标签的父节点。

    In [46]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
    In [47]: doc.find('.//p').drop_tag()
    
    In [48]: lxml.html.tostring(doc)
    Out[48]: b'<div class="post" id="123">abc<a href="/to-go">link</a></div>'
    
    

    .drop_tree()方法

    移除该节及其子节点和文本,而它后面的文本(尾文)合并到前面一个节点或父节点。

    In [50]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
    In [51]: doc.find('.//p').drop_tree()
    
    In [52]: lxml.html.tostring(doc)
    Out[52]: b'<div class="post" id="123"></div>'
    
    

    .find(path),. find(path),. findtext(path)方法

    通过路径(Xpath的)或标签查找特定节点,前者返回找到的第一个,第二个返回找到的全部HTML元素,第三个返回找到的第一个的节点的文本(的.text)

    In [55]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
    
    In [56]: doc.find('p')
    Out[56]: <Element p at 0x7fc40a4dd6d8>
    
    In [57]: doc.find('.//a')
    Out[57]: <Element a at 0x7fc409fee4a8>
    
    In [58]: doc.findall('p')
    Out[58]: [<Element p at 0x7fc40a4dd6d8>]
    
    In [76]: doc.findtext('.//a')
    Out[76]: 'link'
    
    

    .find_class(CLASS_NAME)方法

    通过类名称查找所有含有CLASS_NAME的元素,返回的HtmlElement的列表

    In [70]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p><p class="para p2"></p></div>')
    
    In [71]: doc.find_class('para')
    Out[71]: [<Element p at 0x7fc40a3ff278>, <Element p at 0x7fc40a3ffc78>]
    
    

    .get_element_by_id(id)方法

    得到第一个ID为输入ID的节点。如果有多个相同ID的节点(按道理讲,一个HTML文档里面的ID是唯一的)只返回第一个。

    In [79]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
    
    In [80]: doc.get_element_by_id('123')
    Out[80]: <Element div at 0x7fc409fda2c8>
    
    

    .getchildren(),getparent()方法

    顾名思义,获得孩子节点和父节点。需要注意的是,还是可以有多个(返回列表),父亲只有一个。

    In [83]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
    
    In [84]: doc.getchildren()
    Out[84]: [<Element p at 0x7fc410836b38>]
    
    In [85]: doc.getparent()
    Out[85]: <Element body at 0x7fc40a3ff9a8>
    # 注意:输入的本没有body,div已经是最上层节点,它的父节点就是body了
    
    

    .getnext()。getprevious()方法

    获取后一个或前一个节点,如果没有则返回无。

    In [109]: doc = lxml.html.fromstring('<div><p>abc</p><p>xyz</p></div>')
    In [110]: doc.getnext()
    
    In [111]: doc.find('p').getnext()
    Out[111]: <Element p at 0x7fc409fdad68>
    
    In [112]: doc.find('p').getprevious()
    
    

    .getiterator(),. iter()方法

    从该节点开始,按文档顺序(深度优先)遍历所有子节点。可以指定只遍历某些标签。

    In [127]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
    In [128]: for itr in doc.getiterator():
         ...:     print(itr.tag)
         ...: 
    div
    p
    a
    In [129]: for itr in doc.iter():
         ...:     print(itr.tag)
         ...: 
    div
    p
    a
    
    

    .iterchildren()方法

    只遍历子节点。

    .iterancestors()。iterdescendants()方法

    前者遍历前辈(从父亲节点开始),后者遍历后辈(从子辈开始),都跳过该节点。

    In [134]: doc = lxml.html.fromstring('<div class="post" id="123"><p class="para">abc<a href="/to-go">link</a></p></div>')
    
    In [135]: a = doc.find('.//a')
    
    In [136]: for itr in doc.iterancestors():
         ...:     print(itr.tag)
         ...: 
    body
    html
    
    In [137]: for itr in a.iterancestors():
         ...:     print(itr.tag)
         ...: 
    p
    div
    body
    html
    
    In [138]: for itr in doc.iterdescendants():
         ...:     print(itr.tag)
         ...: 
    p
    a
    
    

    .iterfind(path)方法

    遍历所有符合路径的子节点,类似于的findall()

    .make_links_absolute(BASE_URL)

    很多网页的链接都是类似HREF =” /路径/ a.html”没有写全网址,这个方法的作用就是补全网址。

    .tag属性

    该节点的html标签名称

    .text .tail属性

    都是该节点的文本内容,不同的是一个在标签内,一个在尾部:

    <p>text</p>tail
    
    

    再看下面的代码

    In [173]: doc = lxml.html.fromstring('<div><p class="para">abc<a href="/to-go">link</a>worod</p>apple</div>')
    
    In [174]: p = doc.find('p')
    
    In [175]: p.text
    Out[175]: 'abc'
    
    In [176]: p.tail
    Out[176]: 'apple'
    
    

    .text_content()方法

    返回给节点及其子节点包含的所有文本

    In [178]: doc.text_content()
    Out[178]: 'abclinkworodapple'
    
    

    以上就是我们从网页提取内容时用到的主要属性和方法。下一节,我们将以实例讲解具体提取数据的过程。

    相关文章

      网友评论

        本文标题:Python爬虫网页,解析工具lxml.html(二)

        本文链接:https://www.haomeiwen.com/subject/uwzunqtx.html