• Python-选择器Xpath,Css,Re


    正则表达式(特殊字符)

    chrome控制台搜索:$x('//*[@id="body_container"]/div[3]/div[2]/div/div/a[1]/@href')

    ^                            开头  '^b.*'----以b开头的任意字符
     
    $                            结尾  '^b.*3$'----以b开头,3结尾的任意字符  
     
    *                            任意长度(次数),≥0
     
    ?                            非贪婪模式,非贪婪模式尽可能少的匹配所搜索的字符串  '.*?(b.*?b).*'----从左至右第一个b和的二个b之间的内容(包含b)
     
    +                            一次或多次
     
    {2}                          指定出现次数2次
     
    {2,}                         出现次数≥2次
     
    {2,5}                        出现次数2≤x≤5
     
    |                            或   “z|food”----能匹配“z”或“food”(此处请谨慎)。“[z|f]ood”----则匹配“zood”或“food”或"zood"
     
    []                           括号中任意一个符合即可(中括号里面没有分转义字符)  '[abc]ooby123'----只要开头符合[]中任意一个即可
     
    [^]                          只要不出现[]的即可
     
    [a-Z]                        从小a到大Z
     
    .                            任意字符
     
    s                           匹配不可见字符 
     	  '你s好'----可以匹配‘你 好’
     
    S                           匹配可见字符,即普通字符
     
    w                           匹配下划线在内的任何单词字符
     
    W                           和上一个相反
     
    [u4E00-u9FA5]              只能匹配汉字
    ()                           要取出的信息就用括号括起来
     
    d                           数字
    

     寻找2个字或者3个字的XX市或者XXX区 

    re.findall(re.compile('([u4e00-u9fa5]{2}市|[u4e00-u9fa5]{2}区|[u4e00-u9fa5]{3}市|[u4e00-u9fa5]{3}区)', re.S),
    [u4e00-u9fa5]过滤中文


    Xpath

    article                      选取所有article元素的所有子节点
     
    /article                     选取根元素article
     
    article/a                    选取所有属于article的子元素的a元素
     
    //div                        选取所有div子元素(不论出现在文档任何地方)
     
    article//div                 选取所有属于article元素的后代的div元素不管它出现在article之下的任何位置
     
    //@class                     选取所有名为class的属性
     
    /article/div[1]              选取属于srticle子元素的第一个div所有子节点
     
    /article/div[last()]         选取属于article子元素的最后一个div所有子节点
     
    /article/div[last()-1]       选取属于article子元素的倒数第二个div所有子节点
     
    //div[@lang]                 选取所有拥有lang属性的div元素
     
    //div[@lang='eng']           选取所有lang属性为eng的div元素
     
    /div/*                       选取属于div元素的所有子节点
     
    //*                          选取所有元素
     
    //div[@*]                    选取所有带属性的div元素
     
    //div/a | //div/p            选取所有div元素的a个p元素
     
    //span | //ul                选取文档中的span和ul元素
     
    article/div/p | //span       选取所有属于article元素的div元素和所有的span元素
    

    1. 取得文章标题

    复制代码
    >>> title = response.xpath('//div[@class="entry-header"]/h1/text()')
    >>> title
    [<Selector xpath='//div[@class="entry-header"]/h1/text()' data='2016 腾讯软件开发面试题(部分)'>]
    >>> title.extract()
    ['2016 腾讯软件开发面试题(部分)']
    >>> title.extract()[0]
    '2016 腾讯软件开发面试题(部分)'
    >>> title.extract_first()
    '2016 腾讯软件开发面试题(部分)'
    复制代码
    说明
    1)extract()方法会把原数据的selector类型转变为列表类型
    2)extract()会得到多个值,extract()[1]取第2个值
    3)extract_first()得到第一个值,类型为字符串。extract_first(default='')如果没取到返回默认值
     
     
    2. 取得发表日期
    >>> response.xpath("//p[@class='entry-meta-hide-on-mobile']/text()").extract()[0].strip().replace("·","").strip()
    '2017/02/18'
     
    3. 点赞数,span标签里有很多class名,选一个看起来像唯一的,测试一下,然后用contains()函数简化操作
    >>> response.xpath("//span[contains(@class, 'vote-post-up')]/h10/text()").extract()
    ['2']
    >>> response.xpath("//span[contains(@class, 'vote-post-up')]/h10/text()").extract()[0]
    '2'
    >>> int(response.xpath("//span[contains(@class, 'vote-post-up')]/h10/text()").extract()[0])
    2

     

    Xpath函数

     
    4. 收藏数,要用正则,re模块也是scrapy的内置模块,注意要用非贪婪匹配,否则只会取到8
    复制代码
    >>> response.xpath("//span[contains(@class, 'bookmark-btn')]/text()").extract()[0]
    ' 28 收藏'
    >>> string = response.xpath("//span[contains(@class, 'bookmark-btn')]/text()").extract()[0]
    >>> import re
    >>> pattern = re.match(".*?(d+).*", string)
    >>> pattern.group(1)
    '28'
    复制代码

     可以简写为

    >>> response.xpath("//span[contains(@class, 'bookmark-btn')]/text()").re('.*?(d+).*')
    ['28']
    >>> response.xpath("//span[contains(@class, 'bookmark-btn')]/text()").re('.*?(d+).*')[0]
    '28'

     节点轴选择

     

    5. 使用列表推导式取得一个标签中的部分元素,如下取得职场和面试字样。适用于有些文章没评论标签的情况
    复制代码
    找到不是以"评论"结尾的元素
    >>> response.xpath("//p[@class='entry-meta-hide-on-mobile']/a/text()").extract()
    ['职场', ' 9 评论 ', '面试']
    >>> tag_list = response.xpath("//p[@class='entry-meta-hide-on-mobile']/a/text()").extract()
    >>> [element for element in tag_list if not element.strip().endswith("评论")]
    ['职场', '面试']
    >>> tag_choose=[element for element in tag_list if not element.strip().endswith("评论")]
    >>> tags=",".join(tag_choose)
    >>> tags
    '职场,面试'
    复制代码
    join()函数基本语法: 'sep'.join(seq)。表示以sep为分隔符,将seq中所有的元素合并成一个新的字符串
    sep表示分隔符,可以为空;
    seq表示要连接的数据,数据类型可以是列表,字符串,元组或者字典
     
    • Element类型是'lxml.etree._Element',某种意义来说同时是一个列表
    • 列表的需要使用tagattrib ext三个不同的属性来获取我们需要的东西
    • 变量.tag获取到的是标签名是---字符串
    • 变量.attrib获取到的是节点标签a的属性---字典
    • 变量.text获取到的是标签文本--字符串  

    xpath表格中取值

    Ptable_items = response.xpath("//div[@class='Ptable']/div[@class='Ptable-item']/dl/dl")
            others = {}
            for item in Ptable_items:
                dt = item.xpath("./dt/text()").extract_first().strip()
                dd = item.xpath("./dd/text()").extract_first().strip()
                if "机身内存" in dt:
                    if not one.get("capacity", ""):
                        one["capacity"] = dd
                elif "颜色分类" in dt:
                    if not one.get("color", ""):
                        one["color"] = dd
    

      

    Xpath string()提取多个子节点中的文本

    <div>
        <ul class="show">
            <li>275万购昌平邻铁三居 总价20万买一居</li>
            <li>00万内购五环三居 140万安家东三环</li>
            <li>北京首现零首付楼盘 53万购东5环50平</li>
            <li>京楼盘直降5000 中信府 公园楼王现房</li>
        </ul>
    </div>

    我想要把所有li标签中的文本提取出来,并且放到一个字符串中.
    在网上查了下发现使用xpath的string()函数可以实现(string()和text()的区别请自行google)
    先看下常见的方法:

    >>> from lxml import etree
    ...
    >>> result = html.xpath("//div/ul[@class='show']")[0]
    >>> result.xpath('string(.)')
     '                 275万购昌平邻铁三居 总价20万买一居                 00万内购五
    环三居 140万安家东三环                 北京首现零首付楼盘 53万购东5环50平
      京楼盘直降5000 中信府 公园楼王现房             '

    这是我查到的多数人使用的方法,还有人使用了concat()函数,更麻烦就不提了.
    但是上面的匹配明显感觉可以写到一条xpath里面的,为什么非要分开写!忍不住吐槽一下


    xpath string()函数的调用写法:

    >>> html.xpath("string(//div/ul[@class='show'])")
    '                 275万购昌平邻铁三居 总价20万买一居                 00万内购五
    环三居 140万安家东三环                 北京首现零首付楼盘 53万购东5环50平
      京楼盘直降5000 中信府 公园楼王现房             '

    再吐槽下上面那种写法.在xpath语法里面,点(.)表示当前节点,当前节点不就是html.xpath("//div/ul[@class='show']")[0]取到的节点元素吗!!!

    Css

    *                            选取所有节点
     
    #container                   选取id为container的节点
     
    .container                   选取所有class包含container的节点
     
    li a                         选取所有li下的所有a节点
     
    ul+p                         选取ul后面的第一个p元素
     
    div#container > ul           选取id为container的div的第一个ul子元素
     
    ul ~ p                       选取与ul相邻的所有p元素
     
    a[title]                     选取所有有title属性的a元素
     
    a[href="http://jobbole.com"] 选取所有href属性为jobbole.com
     
    a[href*="jobole"]            选取所有href属性包含jobbole的a元素
     
    a[href^="http"]              选取所有href属性值以http开头的a元素
     
    a[href$=".jpg"]              选取所有href属性值以.jpg结尾的a元素
     
    input[type=radio]:checked    选取选中的radio的元素
     
    div:not(#container)          选取所有id非container的div元素
     
    li:nth-child(3)              选取第三个li元素
     
    tr:nth-child(2n)             第偶数个tr元素
    

      

    ^                            开头  '^b.*'----以b开头的任意字符
     
    $                            结尾  '^b.*3$'----以b开头,3结尾的任意字符  
     
    *                            任意长度(次数),≥0
     
    ?                            非贪婪模式,非贪婪模式尽可能少的匹配所搜索的字符串  '.*?(b.*?b).*'----从左至右第一个b和的二个b之间的内容(包含b)
     
    +                            一次或多次
     
    {2}                          指定出现次数2
     
    {2,}                         出现次数≥2
     
    {2,5}                        出现次数2≤x≤5
     
    |                            或   “z|food”----能匹配“z”或“food”(此处请谨慎)。“[z|f]ood”----则匹配“zood”或“food”或"zood"
     
    []                           括号中任意一个符合即可(中括号里面没有分转义字符)  '[abc]ooby123'----只要开头符合[]中任意一个即可
     
    [^]                          只要不出现[]的即可
     
    [a-Z]                        从小a到大Z
     
    .                            任意字符
     
    s                           匹配不可见字符   '你s好'----可以匹配‘你 好’
     
    S                           匹配可见字符,即普通字符
     
    w                           匹配下划线在内的任何单词字符
     
    W                           和上一个相反
     
    [u4E00-u9FA5]              只能匹配汉字
    ()                           要取出的信息就用括号括起来
     
    d                           数字
  • 相关阅读:
    iOS通知的使用
    使用代理和block写一个alertView
    MongoDB的访问权限和用户设置
    编写高效SQL语句
    Linux 安装 jdk 环境
    基于3dsMax的地图编辑器设想
    入驻cnBlogs!
    毕设开发总结3D游戏框架及网络对战游戏的开发(1)
    gkENGINE 个人图形引擎展示
    利用D3DQUERY实现简单的GPU计时器
  • 原文地址:https://www.cnblogs.com/du-jun/p/10274206.html
Copyright © 2020-2023  润新知