Day 5【Datawhale】爬虫入门学习——XPath学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27283619/article/details/89150774

1 学习XPath

1.1 什么是XPath

XPath全称XML Path Language,即XML路径语言。XPath主要使用在XML文档中选择节点,同时XPath也适用于HTML。

  • XPath 使用路径表达式在 XML 文档中进行导航
  • XPath 包含一个标准函数库
  • XPath 是 XSLT 中的主要元素
  • XPath 是一个 W3C 标准

1.2 节点及节点的关系

  1. 节点
    在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。
  2. 节点关系
    这个跟在bs4库中的是类似的。
  • 父(Parent)
    每个元素以及属性都有一个父。
  • 子(Children)
    元素节点可有零个、一个或多个子。
  • 同胞(Sibling)
    拥有相同的父的节点
  • 先辈(Ancestor)
    某节点的父、父的父,等等。
  • 后代(Descendant)
    某个节点的子,子的子,等等。

1.3 XPath语法

XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取。

  • 选取节点
    XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。
    XPath要定位到我们需要的节点,多级选取和跳级选取中要多配合属性等来达到准确定位,其次要注意多余匹配情况的发生,检查结果是否准确!
表达式 描述
nodename 选取此节点下的所有子节点
/ 多级选取,从根节点开始选取
// 跳级选取,用的比较多,以列表形式,返回所有匹配的节点对象
. 选取当前节点
选取当前节点的父节点
@ 选取属性

示例:
在这里插入图片描述

  • 谓语(Predicates)
    谓语用来查找某个特定的节点或者包含某个指定的值的节点。
    谓语被嵌在方括号中。
    在下面的表格中,列出了带有谓语的一些路径表达式,以及表达式的结果:
    在这里插入图片描述
  • 通配符-"*"
    在这里插入图片描述
  • 运算符 “|”
    在这里插入图片描述

1.4 XPath 轴(Axes)

轴可定义相对于当前节点的节点集。
在这里插入图片描述

1.5 获取文本和属性信息

  • 获取文本信息text()方法
result = html.xpath('//li/text()')
  • 获取属性信息
result = html.xpath('//li/@属性名')

提取信息部分可以参考我的另外一篇文章Scrapy中XPath选择器的基本用法

2 项目实战——基于lxml+XPath+requests不登录爬取丁香园论坛的回复信息

2.1 目标

爬取丁香园论坛http://www.dxy.cn/bbs/thread/626626#626626上的回复内容。
说明:因为不登录只能爬取到4条。

2.2 思路

  • 第一步准确定位到回复信息所在的标签
    发现我们需要的信息都在<td class="postbody”>中,所以定位到这个标签。
# 以列表形式,返回所有包含所需信息的td标签
ls = tree.xpath('//td[@class="postbody"]')
  • 第二步提取信息
    我们需要的信息都在text中,对比string()和text()方法,我这里选择的是text(),因为它的打印输出比string()好一些。其中添加’\n’的作用是保证和原网页相近的格式输出(本质就是实现换行);
    推荐大家看看我的这篇文章XPath中text方法和string方法的用法总结
ls_ms.append('\n'.join(ls[i].xpath('.//text()')).strip())  # 把每个td标签中的信息放入列表中

3 完整代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2019/4/9 13:41

@author: Jock
"""


import requests
from lxml import etree
import time

# get_html_text(url)获取网页信息
def get_html_text(url):
    try:
        r = requests.get(url)  # 爬取完整的网页数据
        r.raise_for_status()  # 如果状态不是200,引发HTTPError异常
        return r.text  # 以字符串的形式返回爬取的网页内容
    except:
        print("访问出错")
        return ""  # 发生异常,返回空字符串

# extract_data(data)提取网页内容
def extract_data(data):
    # 做好ElementTree
    tree = etree.HTML(data)
    # 列表ls_ms回复信息
    ls_ms = []
    # 以列表形式,返回所有包含所需信息的td标签
    ls = tree.xpath('//td[@class="postbody"]')
    n = len(ls)
    for i in range(n):
        try:
            ls_ms.append('\n'.join(ls[i].xpath('.//text()')).strip())  # 把每个td标签中的信息放入列表中
        except:
            print('出错')
            continue
    return ls_ms

# 主函数
def main():
    url = 'http://www.dxy.cn/bbs/thread/626626#626626'
    data = get_html_text(url)
    ls_ms = extract_data(data)
    n = len(ls_ms)
    print('【问题】:' + ls_ms[0])
    for i in range(1,n):
        print('【回复'+ str(i) + '】是:', end='')
        print(ls_ms[i])

# 测试时间
def count_spend_time(func):
    start_time = time.time()
    func()
    end_time = time.time()
    time_dif = (end_time - start_time)
    second = time_dif%60
    minute = (time_dif//60)%60
    hour = (time_dif//60)//60
    print('spend ' + str(hour) + 'hours,' + str(minute) + 'minutes,' + str(second) + 'seconds')

if __name__ == '__main__':
    count_spend_time(main)

4 参考资料

  1. XPath Tutorial
  2. XPath 教程
  3. lxml官方文档

猜你喜欢

转载自blog.csdn.net/qq_27283619/article/details/89150774