• scrapy Selector用法及xpath语法


    准备工作

    html示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <html
    <head>
        <title>text</title>
    </head>
    
    <body>
    
    <div class="cdiv">
        <p class="cp1 section">test p1 <span>next p1</span></p>
        <ul>
            <li id="0">1</li>
            <li id="1">2</li>
            <li id="2">3</li>
        </ul>
    </div>
    
    <div class="cdiv1">
         <p class="cp2">test p2 <span>next p2</span></p>
         <ul>
            <li id="3">4</li>
            <li id="4">5</li>
            <li id="5">6</li>
        </ul>
    </div>
    
    <p class="item">test in p </p>
    
    <li id="6" class="item cli-1">7</li>
    <li id="7" class="item cli-2">8</li>
    
    
    </body>
    
    </html>
    

    把该示例保存到test.html中.

    创建python文件,输入代码

    from scrapy.selector import Selector
    
    doc = ''
    with open('./test.html', 'r') as f:
        doc = f.read()
    
    sel = Selector(text=doc)
    

    后面所有的示例代码都会添加到这个文件中

    Selector的主要方法

    得到选中节点的字符串

    get(): 得到选中节点列表中的第一个中节点, 并转换成字符串返回。

    getall(): 得到选中节点列表中的所有节点,并转换成字符串返回。

    示例:

    #得到选中节点字符串
    res = sel.css('.cdiv').xpath(".//li").get()
    print(res)
    res = sel.css('.cdiv').xpath(".//li").getall()
    print(res)
    

    结果:

    <li id="0">1</li>
    ['<li id="0">1</li>', '<li id="1">2</li>', '<li id="2">3</li>']
    

    用正则表达式匹配

    re(regex): 用正则表达式匹配节点,并返回匹配的字符串。

    示例:

    res = sel.css('body .item').re(r'cli-d+')
    print(res)
    

    结果:

    ['cli-1', 'cli-2']
    

    使用xpath表达式选择节点

    xpath(query): 使用xpath表达式选择节点, 并返包含选中节点的Selector对象.

    使用css选择器选中节点

    css(query): 使用css选择器表达式选择节点, 并返包含选中节点的Selector对象

    xpath 语法

    选择所有的子节点

    //{node}: 选择根节点下所有标签为{node}的子节点.

    //{node}//{node1}: 选择根节点下所有标签为{node1}且父节点包含标签{node}的节点

    示例1:

    res = sel.xpath("//li")
    print(res)
    

    结果:

    [<Selector xpath='//li' data='<li id="0">1</li>'>, <Selector xpath='//li' data='<li id="1">2</li>'>, <Selector xpath='//li' data='<li id="2">3</li>'>, <Selector xpath='//li' data='<li id="3">4</li>'>, <Selector xpath='//li' data='<li id="4">5</li>'>, <Selector xpath='//li' data='<li id="5">6</li>'>, <Selector xpath='//li' data='<li id="6" class="item cli-1">7</li>'>, <Selector xpath='//li' data='<li id="7" class="item cli-2">8</li>'>]
    

    示例2

    res = sel.xpath("//ul//li")
    print(res)
    

    结果

    [
    <Selector xpath='//ul//li' data='<li>1</li>'>, 
    <Selector xpath='//ul//li' data='<li>2</li>'>, 
    <Selector xpath='//ul//li' data='<li>3</li>'>, 
    <Selector xpath='//ul//li' data='<li>4</li>'>, 
    <Selector xpath='//ul//li' data='<li>5</li>'>,
    <Selector xpath='//ul//li' data='<li>6</li>'>
    ]
    

    选择直接子节点

    {node}/{node1}: 选择从{node}的直接子节点中选择标签为{node1}节点.

    示例1:

    res = sel.xpath("//body/li")
    print(res)
    
    

    结果:

    [<Selector xpath='//body/li' data='<li id="6" class="item cli-1">7</li>'>, <Selector xpath='//body/li' data='<li id="7" class="item cli-2">8</li>'>]
    

    从选择的子节点列表中选择第n个子节点

    //{node}[n]: 先把兄弟节点聚合在一个list变成[list_1, list_2, ...], 然后从每个list中选择第n个, 如果list的长度不足n个则跳过.

    (//{node})[n]: 把所有选择的节点放在一条list, 然后从这个list中选择第n个

    示例1:

    res = sel.xpath("//li[1]")
    print(res)
    res = sel.xpath("//li[3]")
    print(res)
    

    结果:

    [<Selector xpath='//li[1]' data='<li id="0">1</li>'>, <Selector xpath='//li[1]' data='<li id="3">4</li>'>, <Selector xpath='//li[1]' data='<li id="6" class="item cli-1">7</li>'>]
    [<Selector xpath='//li[3]' data='<li id="2">3</li>'>, <Selector xpath='//li[3]' data='<li id="5">6</li>'>]
    

    示例2

    res = sel.xpath("(//li)[1]")
    print(res)
    res = sel.xpath("(//li)[3]")
    print(res)
    

    结果:

    [<Selector xpath='(//li)[1]' data='<li>1</li>'>]
    [<Selector xpath='(//li)[3]' data='<li>3</li>'>]
    

    使用节点属性作为选择条件

    {node}[@{attr}='{val}']: 选中节点必须有名字为{attr}的属性, 且这个属性的值等于{val}.

    {node}[contains(@{attr}, '{val}']: 选中节点必须有名字为'{attr}'的属性, 且这个属性的值包含{val}.

    示例1

    res = sel.xpath("//p[@class='cp1']")
    print(res)
    res = sel.xpath("//p[@class='cp2']")
    print(res)
    res = sel.xpath("//p[contains(@class, 'cp1')]")
    print(res)
    

    结果

    []
    [<Selector xpath="//p[@class='cp2']" data='<p class="cp2">test p2 <span>next p2<...'>]
    [<Selector xpath="//p[contains(@class, 'cp1')]" data='<p class="cp1 section">test p1 <span>...'>]
    [<Selector xpath="descendant-or-self::p[@class and contains(concat(' ', normalize-space(@class), ' '), ' cp1 ')]" data='<p class="cp1 section">test p1 <span>...'>]
    

    在包含条件中, 如果使用'class'属性, 可以用css选择器简化:

    示例2:

    res = sel.css("p.cp1")
    print(res)
    

    结果:

    [<Selector xpath="descendant-or-self::p[@class and contains(concat(' ', normalize-space(@class), ' '), ' cp1 ')]" data='<p class="cp1 section">test p1 <span>...'>]
    

    提取节点属性的值

    {node}/@{attr}: 提取选择节的点中属性名为{attr}的值.

    示例1:

    res = sel.xpath("//p/@class")
    print(res)
    print("
    ")
    

    结果

    [<Selector xpath='//p/@class' data='cp1 section'>, <Selector xpath='//p/@class' data='cp2'>]
    

    提取节点中的文本内容

    {node}/text(): 提取当前选择节点的文本内容, 不包括子节点的文本.

    {node}//text(): 提取选择节点的文本内容, 包括子节点的文本.

    示例1:

    res = sel.xpath("//p//text()")
    print(res)
    res = sel.xpath("//p/text()")
    print(res)
    

    结果:

    [<Selector xpath='//p//text()' data='test p1 '>, <Selector xpath='//p//text()' data='next p1'>, <Selector xpath='//p//text()' data='test p2 '>, <Selector xpath='//p//text()' data='next p2'>]
    [<Selector xpath='//p/text()' data='test p1 '>, <Selector xpath='//p/text()' data='test p2 '>]
    

    在xpath表达式中使用变量

    在xpath表达式中是${varname}定义变量, 类似于bash

    示例1:

    #使用变量$val
    res = sel.xpath("//li[@id=$val]", val='1')
    print(res)
    res = sel.xpath("//li[@id=$val]", val='3')
    print(res)
    res = sel.xpath("//li[@id=$val]", val='6')
    print(res)
    

    结果:

    [<Selector xpath='//li[@id=$val]' data='<li id="1">2</li>'>]
    [<Selector xpath='//li[@id=$val]' data='<li id="3">4</li>'>]
    [<Selector xpath='//li[@id=$val]' data='<li id="6" class="item cli-1">7</li>'>]
    
  • 相关阅读:
    ocilib(简介2)
    C++ Socket编程步骤 (转载)
    服务端和客户端的疑问
    var和public的区别
    vs2010如何设置能实现输入关键字的时候自动提示呢?
    ocilib(简介)
    iostream.h , iostream
    error C2110: cannot add two pointers
    Array 越界不报错的问题
    char* + int or char or ...
  • 原文地址:https://www.cnblogs.com/brandonli/p/12654396.html
Copyright © 2020-2023  润新知