简单抓站的N种方式(三)-lxml与xpath

作者: 周且南_laygin | 来源:发表于2017-07-28 16:55 被阅读220次

    使用lxml可以解析html文档,其中需要用到xpath来选取节点,包括元素、属性、文本、命名空间、处理指令、注释和根节点。下面简单介绍一下xpath,也方便自己不时查阅,随后用一个例子具体演示使用xpath是如何抓取html文档内容的。

    一、xpath简介

    1、路径表达式

    表达式 概述
    nodename 选取此节点的所有子节点。
    / 从根节点选取 [绝对路径]
    // 从匹配的当前节点选择文档中的节点 [相对路径]
    . 选取当前节点。
    .. 选取当前节点的父节点。
    @ 选取属性。

    2、表达式例子

    路径表达式 表意
    div 选取div元素下的的所有子节点。
    /div 从根节点选取div [绝对路径]
    body/div 选取属于body子元素的所有div元素
    //div 选取该文档中所有div元素 [相对路径]
    body//div 选取属于body后代的所有div元素
    //@class 选取名为class的所有属性。

    3、谓语

    谓语放在方括号中用于选取特定的节点

    路径表达式 结果
    /body/div[1] 选取body元素下的第一个div。
    /body/div[last()] 选取body元素下的最后一个div。
    /body/div[last()-1] 选取body元素下的倒数第二个div。[以此类推]
    //div[@class] 选取所有属性名为class的div元素。
    //div[@class="age"] 选取所有属性名为class并且值为age的div元素

    4、未知节点的选取

    选取未知的节点,需要用到xpath的通配符,基本与正则类同

    通配符 表意
    * 任意元素节点
    @* 任意属性节点
    node() 任意类型节点

    如:

    路径表达式 结果
    /body/* 选取body元素的所有子元素。
    //* 选取文档中的所有元素。
    //div[@*] 选取带有任意属性的div

    5、多路径的选取

    在网络爬虫中,经常会遇到这一页的内容放在一个div下,下一页就放到p标签下面了,或者标签属性不一样等等。这种情况就需要用到多路径的选取策略,相当于逻辑表达式里所说的

    使用运算符| 可实现多路径的选取

    路径表达式 结果
    //body/div | //body/p 选取body元素的所有div和p元素。
    //div | //p 选取文档中的所有div和p元素。

    关于xpath的基础知识有这些基本就够了,等遇到比较复杂的网页时,也能从这些基本的表达中变通得来

    二、使用lxml抓站

    1、简介

    • 首先还是需要得到html文档,这里使用requests
    • 其次使用lxml的etree解析html
    • 最后通过xpath选取需要的节点内容
    大致流程

    通过抓取豆瓣读书的书单列表简单演示一下,以备后查。
    目标网页长成这个样子,我需要把书名和简介抓取下来,其余内容类似,比如作者、评分啊等等都可以。

    目标网页-豆瓣读书

    2、源码

    def douban_book():
        '''拿豆瓣读书来试一试'''
        from lxml import etree
        import re
    
        url = r'https://book.douban.com/latest?icn=index-latestbook-all'
        header = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1'}
        html = requests.get(url,headers = header).text
        lhtml = etree.HTML(html)
        #找到虚构类和非虚构类的所有图书
        all_book = lhtml.xpath('//div[@class="article" or @class="aside"]//li/div')
        
        for book in all_book:
            #找到图书标题
            book_title = re.sub(r'[\n\t\s]+','',''.join(book.xpath('h2//text()')))  #使用正则去掉换行空格等字符
            #图书简介,其余字段类似
            detail = re.sub(r'[\n\t\s]+','',''.join(book.xpath('p[@class="detail" or not(@class)]/text()')))  #因为还有一部分p标签是没有属性的,注意这里的or与not
            yield {book_title:detail}   #返回字典,也可以保存到文本或数据库
    

    调用测试代码:

        for book in douban_book():
            print(book)
    

    3、结果

    结果

    相关文章

      网友评论

        本文标题:简单抓站的N种方式(三)-lxml与xpath

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