• xpath教程三---逐层检索和全局检索


    本节主要介绍用xpath来描述html的层级关系

    主要使用到的知识点如下:

    • 单独的一个点 .,表示当前位置
    • 两个点 ..,表示上一级父标签的位置
    • 单独的一个斜杠 /,表示只检索下面一级
    • 单独的两个斜杠 //,表示检索下面全部位置
    • 下标 [数字]:从1开始,依次计算

    准备代码

    首先是一个HTML代码块,以及lxml的代码

    html_str = """
    <body>
    <div class="ui container">
    
            <table class="ui striped  table">
                <tr>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>邮箱</th>
                    <th>电话</th>
                </tr>
                <tr>
                    <td><a href="zhangwei">张伟</a></td>
                    <td>男</td>
                    <td>zhangwei@haoren.com</td>
                    <td>12138-111</td>
                </tr>
                <tr>
                    <td><a href="yifei">一菲</a></td>
                    <td>女</td>
                    <td>yifei@haoren.com</td>
                    <td>12138-112</td>
                </tr>
                <tr>
                    <td><a href="xiaoxian">小贤</a></td>
                    <td>男</td>
                    <td>xiaoxian@haoren.com</td>
                    <td>12138-113</td>
                </tr>
                <tr>
                    <td><a href="meijia">美嘉</a></td>
                    <td>女</td>
                    <td>meijia@haoren.com</td>
                    <td>12138-114</td>
                </tr>
                <tr>
                    <td><a href="xiaobu">小布</a></td>
                    <td>男</td>
                    <td>xiaobu@hundan.com</td>
                    <td>12138-115</td>
                </tr>
    
            </table>
    </div>
    </body>
    """
    
    from lxml import etree
    
    html = etree.HTML(html_str)
    

    这次的html,主要是表格,还都是些名字,现在开始后面的任务吧

    任务一:获取表格头部【即第一栏 tr 标签】的所有 th 标签文本值

    当前html就一个表格,然后取得第一个 tr 标签,再提取里面 th 标签的文本即可,xpath如下:

    print(html.xpath('.//table/tr[1]/th/text()'))
    print(html.xpath('.//table/tr/th/text()')) # 这个规则也行,因为 th 标签只有这里有
    

    运行结果:['姓名', '性别', '邮箱', '电话']

    任务二:提起五条记录中的全部电话

    提取表格记录中的全部电话文本,这里就涉及了五个 tr 标签,且都是最后一个td标签,所以这里先获取全部的tr,然后再拿第四个td标签即可,xpath如下:

    print(html.xpath('.//table/tr/td[4]/text()'))
    

    运行结果:['12138-111', '12138-112', '12138-113', '12138-114', '12138-115']

    任务三:获取所有性别为男的所有姓名

    这个任务稍微有点绕弯,因为性格和姓名的两个标签,不是父子级关系【用以前的方法,性别为父姓名为子是可以正常获取的】,而是同级再嵌套【姓名在a标签下面】的关系。

    所以这里需要用的知识点是比较、父级跳出、获取同级的子级文本,一步步来,如下步骤:

    1、第一步:获取性别为男的文本,xpath规则如下:

    print(html.xpath('.//table/tr/td[text()="男"]/text()'))
    

    运行结果:['男', '男', '男']

    2、获取到之后,往外跳一层,得到对应的三个tr标签,xpath规则如下:

    print(html.xpath('.//table/tr/td[text()="男"]/..'))
    

    运行结果:[<Element tr at 0x1fd15543808>, <Element tr at 0x1fd15543848>, <Element tr at 0x1fd15543748>]【虽然结果看不出什么,但是从数量来看,是三个而不是五个】

    3、到了这里就简单多了,因为姓名是第一个td标签下的a标签,直接获取下标1的文本值,简单明了

    print(html.xpath('.//table/tr/td[text()="男"]/../td[1]/a/text()'))
    

    运行结果:['张伟', '小贤', '小布']

    任务四:仔细观察邮箱,获取所有是 haoren 邮箱的姓名

    通过任务三的训练,四的难度更上一层楼,因为这里涉及一个前面没出现的判断——包含关系。

    因为每个人的邮箱是不一样的,但是要获取邮箱中有haoren的邮箱,并输出它的归属人姓名,难点就在这个比较。

    不过难不倒强大的Xpath,介绍一个函数:contains(字符串, 子串)。函数接收两参数,用当前情况来讲,前面是完整邮箱,后面是"haoren",就这么简单。

    下面是具体使用示例,获取符合规格的好人邮箱:

    print(html.xpath('.//table/tr/td[contains(text(),"haoren")]/text()'))
    

    运行结果:['zhangwei@haoren.com', 'yifei@haoren.com', 'xiaoxian@haoren.com', 'meijia@haoren.com']

    结局挺好,除了小布,其余都是好人

    然后就跳到上级,获取他们的姓名了,xpath规则如下:

    print(html.xpath('.//table/tr/td[contains(text(),"haoren")]/../td/a/text()'))
    

    运行结果:['张伟', '一菲', '小贤', '美嘉']

    任务五:一条xpath,获取出张伟的全部信息【姓名、性别、邮箱、电话】

    表格一般都是统一的规则,按理出牌,td里面套a是不太合规的,但是html语言是没有对错的,不关闭标签都是可以的。

    既然任务有这条,那就用点不一样的思维来理解xpath:text()是获取文本的,一般使用,都是在没有子级标签中,这样可以防止空格、换行的问题。

    但是姓名栏的td标签内,只有a标签,除了a标签空格都没有,这就很好办了,用双斜杠+text()来获取姓名。

    而且除了姓名的td,双斜杠+text()这个用法,对其余三栏不会有任何问题,然后问题就顺顺滑滑的解决了

    最终的xpath如下:

    print(html.xpath('.//table/tr[2]/td//text()'))
    

    结果['张伟', '男', 'zhangwei@haoren.com', '12138-111']

    最终的代码和运行截图

    html_str = """
    <body>
    <div>
    
            <table>
                <tr>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>邮箱</th>
                    <th>电话</th>
                </tr>
                <tr>
                    <td><a href="zhangwei">张伟</a></td>
                    <td>男</td>
                    <td>zhangwei@haoren.com</td>
                    <td>12138-111</td>
                </tr>
                <tr>
                    <td><a href="yifei">一菲</a></td>
                    <td>女</td>
                    <td>yifei@haoren.com</td>
                    <td>12138-112</td>
                </tr>
                <tr>
                    <td><a href="xiaoxian">小贤</a></td>
                    <td>男</td>
                    <td>xiaoxian@haoren.com</td>
                    <td>12138-113</td>
                </tr>
                <tr>
                    <td><a href="meijia">美嘉</a></td>
                    <td>女</td>
                    <td>meijia@haoren.com</td>
                    <td>12138-114</td>
                </tr>
                <tr>
                    <td><a href="xiaobu">小布</a></td>
                    <td>男</td>
                    <td>xiaobu@hundan.com</td>
                    <td>12138-115</td>
                </tr>
    
            </table>
    </div>
    </body>
    """
    
    from lxml import etree
    
    html = etree.HTML(html_str)
    # 任务一
    print(html.xpath('.//table/tr[1]/th/text()'))
    print(html.xpath('.//table/tr/th/text()'))
    # 任务二
    print(html.xpath('.//table/tr/td[4]/text()'))
    # 任务三
    print(html.xpath('.//table/tr/td[text()="男"]/text()'))
    print(html.xpath('.//table/tr/td[text()="男"]/..'))
    print(html.xpath('.//table/tr/td[text()="男"]/../td[1]/a/text()'))
    # 任务四
    print(html.xpath('.//table/tr/td[contains(text(),"haoren")]/text()'))
    print(html.xpath('.//table/tr/td[contains(text(),"haoren")]/../td/a/text()'))
    # 任务五
    print(html.xpath('.//table/tr[2]/td//text()'))
    
    

    xpath_3

    版权声明:允许转载,转载请注明出处 —— 《xpath教程》: 逐层检索和全局检索

  • 相关阅读:
    构建之法东北师大站分数构成
    alpha发布排序结果
    展示一个响应式布局吧,没有效果图自己敲敲看吧@@@@
    vc++和LINGO编程
    [opencv] 极线校正
    [python] 小demo
    [python] socket模块(TCP/IP网络编程)
    树莓派学习【二】:(SSH+VNC)树莓派一根网线连电脑,不要显示屏
    树莓派学习【一】:树莓派的SSH连接
    css+div基本知识;
  • 原文地址:https://www.cnblogs.com/brady-wang/p/8946112.html
Copyright © 2020-2023  润新知