美文网首页
lxml库与Xpath语法

lxml库与Xpath语法

作者: libdream | 来源:发表于2018-12-26 09:30 被阅读0次

    lxml库使用Xpath语法解析定位网页数据。

    lxml库的使用

    (1)修正HTML代码

    lxml为XML解析库,但也很好的支持了HTML文档的解析功能,这为使用lxml库爬取网络信息提供了支持条件。

    (2)读取HTML文件

    除了直接读取字符串,Lxml库还支持从文件中提取内容。

    (3)解析HTML文件

    Xpath语法

    Xpath是一门在XML文档中查找信息的语言,对HTML文档也有很好的支持。

    (1)节点选择

    Xpath使用路径表达式在XML文档中选取节点。节点是通过沿着路径或者step来选取的。

    nodename        #选取此节点的所有子节点
    /               #从根节点选取
    //              #从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
     .              #选取当前节点
    ..              #选取当前节点的父节点
    @               #选取属性
    

    举例说明:

    user_database                #选取元素user_database的所有子节点
    /user_database               #选取根元素user_database。注释:假如路径起始于正斜杠(/),则此路径始终代表到某元素的绝对路径
    user_database/user           #选取属于user_database的子元素的所有user元素
    //user                       #选取所有user子元素,而不管它们在文档中的位置
    user_database//user          #选择属于user_database元素的后代的所有user元素,而不管它们位于user_database之下的什么位置
    //@attribute                 #选取名为 attribute 的所有属性
    

    Xpath语法中的谓语用来查找某个特定的节点或者包含某个指定值的节点,谓语被嵌在方括号中。常见的谓语如下:

    /user_database/user[1]            #选取属于user_database子元素的第一个user元素
    
    //li[@attribute]                  #选取所有拥有名为 attribute 属性的 li 元素
    
    //li[@attribute = 'red']          #选取所有li元素,且这些元素拥有值为 red 的 attribute 属性
    

    Xpath中也可以使用通配符来选取位置的元素,常用的就是“ * ” 通配符,它可以匹配任何元素节点。

    xpath使用技巧

    在爬虫实战中,Xpath路径也可以通过浏览器复制得到,同selector选择器中介绍的方法。

    当需要进行批量爬取时,类似于BeautifulSoup中的selector()方法删除谓语部分不可行的。这时的思路为“先抓大后抓小,寻找循环点”。以从糗事百科的网站爬取用户id为例,打开浏览器进行“检查”,通过“三角形符号”折叠元素,找到每个段子完整的信息标签。

    (1)首先通过复制构造div标签路径,此时的路径为:

     'div[@class="article block untagged mb15"]'
    

    这样就定位到了每个段子信息,这就是“循环点”。

    (2)通过谷歌浏览器进行“检查”定位用户ID,复制Xpath到记事本中:

    //*[@id="qiushi_tag_121251148"]/div[1]/a[2]/h2
    

    因为第一部分为循环部分,将其删除得到:

     div[1]/a[2]/h2
    

    这便是用户ID的信息。

    完整获取用户ID的代码如下:

    import requests
    from lxml import etree
    
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 \
    (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
    
    url = 'https://www.qiushibaike.com/text/'
    r = requests.get(url, headers=headers)
    selector = etree.HTML(r.text)
    url_infos = selector.xpath('//div[@class="article block untagged mb15"]')       
    for url_info in url_infos:
        user_id = url_info.xpath('div[1]/a[2]/h2/text()')[0]        #尾部加上text()获取文本
        print(user_id)
    
    image

    starts-with()

    有时候会遇到相同的字符开头的多个标签:

    <li class="tag-1">需要的内容 1</li>
    
    <li class="tag-2">需要的内容 2</li>
    
    <li class="tag-3">需要的内容 3</li>
    

    想同时爬取时,不需要构造多个Xpath路径,通过starts-with()便可获取多个便签内容,接上例,目前糗事百科按上例的方法已经行不通了,看下图:

    image

    可以发现在 **article block untagged mb15 **的后面增加了typs_long、typs_hot、typs_old等,还按上例那样是匹配不到标签的,这时候就可以用到starts-with(),来提取属性类似的标签信息。

    代码改变如下:

    import requests
    from lxml import etree
    
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 \
    (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
    
    url = 'http://www.qiushibaike.com/text'
    r = requests.get(url, headers=headers)
    selector = etree.HTML(r.text)
    url_infos = selector.xpath('//div[starts-with(@class,"article block untagged mb15")]')
    for url_info in url_infos:
        try:
            user_id = url_info.xpath('div[1]/a[2]/h2/text()')[0]        #尾部加上text()获取文本
        except IndexError:
            user_id = '匿名用户'            #此处遇到匿名用户会抛出IndexError
        print(user_id)
    

    当遇到标签套标签情况时:

    <div class="red">需要的内容 1
            <h1>需要的内容2</h1>
    </div>
    

    想同时爬取文本内容,可以通过string(.)完成:

    from lxml import etree
    html2 = '''
    <div class="red">需要的内容 1
            <h1>需要的内容2</h1>
    </div>
    '''
    selector = etree.HTML(html2)
    content1 = selector.xpath('//div[@class="red"]')[0]
    content2 = content1.xpath('string(.)')
    print(content2)        #string(.)方法可用于标签套标签情况
    
    image

    相关文章

      网友评论

          本文标题:lxml库与Xpath语法

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