Chenerdy的幻想乡
首页文章归档风说书笔记说说友链项目相册关于
← 全部科目

Python爬虫

课次目录

00开篇01爬虫简介02Requests请求03正则04数据解析05selenium自动化06DrissionPage自动化
笔记/Python爬虫/第 04 课

Python爬虫笔记(04):数据解析

2026-09-13 19:00:00

04-数据解析

解析json数据

jsonpath

pip install jsonpath 下载包

jsonpath 是一种用于从 JSON 文档中提取数据的查询语言,类似于 XPath 对 XML 的作用。它提供了一种简洁的方式来定位和提取 JSON 数据中的特定部分

不能直接处理字符串格式, 能直接处理字典,列表数据

JsonPath语法使用

Json结构清晰,可读性高,复杂度低,非常容易匹配,下表中对应了XPath的用法。

JSONPath 描述
$ 根节点
@ 现行节点
.or[] 取子节点
.. 就是不管位置,选择所有符合条件的条件
* 匹配所有元素节点
[] 迭代器标示(可以在里边做简单的迭代操作,如数组下标,根据内容选值等)
[,] 支持迭代器中做多选。
?() 支持过滤操作.

openpyxl存储数据

使用 openpyxl 库创建和操作 Excel 文件

pip install openpyxl

实例
from openpyxl import Workbookwb = Workbook()  # 1. 创建一个新的工作簿 Workbook首字母大写ws = wb.active   # 2. 获取当前活动的工作表(默认第一个)ws.title = "数据"  #3.  设置工作表名称​# 4:使用append添加一行数据   每次使用append都是一行数据ws.append(["学号", "姓名", "成绩", "是否及格"])  # 表头ws.append([1001, "张三", 85, "是"]) ws.append([1002, "李四", 92, "是"])ws.append([1003, "王五", 58, "否"])wb.save("example.xlsx") # 5. 设置文件名称与位置,以及将数据保存至这个文件中

综合案例

异步读取数据, 使用jsonpath, 使用openpyxl库来操作腾讯网要闻数据并且进行翻译了

实例
# 完整版import requestsimport json, timefrom jsonpath import jsonpathfrom openpyxl import Workbook​wb = Workbook()  # 创建一个xlsx表格文件ws = wb.active  # 获取创建的表格文件ws.title = "新闻数据"  # 设置工作表格名称ws.append(["序号", "标题", "时间", "地址", "详情"])  # 表头def spider(url, headers, data):    res = requests.post(url, headers=headers, json=data)    return res.json()    pass​def save_data(result):    title = jsonpath(result, "$.data..title")  # 标题    id = jsonpath(result, "$.data..id")  # 序号    publish_time = jsonpath(result, "$.data..publish_time")  # 时间    long_summary = jsonpath(result, "$.data..long_summary")  # 详情    user_address = jsonpath(result, "$.data..user_address")  # 地址    for title1, id1, publish_time1, long_summary1, user_address1 in zip(title, id, publish_time, long_summary, user_address):        ws.append([id1, title1, publish_time1,user_address1, long_summary1])        print(id1, title1, publish_time1,user_address1, long_summary1)    # 设置文件名称与位置    wb.save("./data/example.xlsx")    pass​if __name__ == "__main__":    url = "https://i.news.qq.com/web_feed/getHotModuleList"    headers = {        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"    }    for i in range(1,5):        print(f"第{i}页")        data = {            "base_req": {                "from": "pc"            },            "forward": "2",            "qimei36": "0_RpPpK7EBAwAEp",            "device_id": "0_RpPpK7EBAwAEp",            "flush_num": i,            "channel_id": "news_news_top",            "item_count": 20        }        result = spider(url, headers, data)        save_data(result)

BeautifulSoup

pip install beautifulsoup4 是一个可以从html与xml文件中提取数据的python库

  • 实例
    BeautifulSoup(markup, features) 

    解析数据

    • markup参数: 要解析的HTML/XML内容
    • features参数: 用哪种 HTML/XML 解析器来解析你的内容
实例
from bs4 import BeautifulSoup  #导包 # 创建BeautifulSoup对象soup = BeautifulSoup(res.text, 'lxml')  # 或使用   # 常用解析器比较 Python内置,无需额外安装soup = BeautifulSoup(res.text, 'html.parser')  ​# 速度快,需要 pip install lxml    				soup = BeautifulSoup(res.text, 'lxml')         ​# 容错性最好,但速度慢 pip install html5lib soup = BeautifulSoup(res.text, 'html5lib')  ​# 安装对应模块之后BeautifulSoup会自动使用
  • pip install lxml 是一种使用python编写的解析库, 可以更加迅速, 灵活的处理XML和HTML

方法

find_all(name=None, attrs={}) 用于查找文档中所有符合条件的标签

  • name: 标签名
  • attrs: 属性

注意: 未查询到返回空列表

find() 与 find_all()参数相同,但只返回第一个匹配结果, 未查询到返回None

get_text() 获取所有文本(包含子标签文本)

select() 与css选择器(js的query获取dom节点)书写一致,获取的是多个, 未查询到返回空列表

实例
# 选择器示例soup.select('ul')           # 所有<ul> ←→ find_all('ul')soup.select('.list')        # class="list" ←→ find_all(class_="list")soup.select('#fruits')      # id="fruits" ←→ find_all(id="fruits")soup.select('ul#fruits')    # id="fruits"的<ul>soup.select('ul > li')      # 直接子元素 ←→ find_all('ul').find_all('li', recursive=False)soup.select('ul li:first-child')  # 每个<ul>的第一个<li>

属性

实例
​tag['属性名']  	  #  不存在会报错tag.attrs['属性名']  #  不存在会报错tag.get("属性名")    # 不存在返回None​tag.attrs 	# 获取所有属性tag.name     # 获取标签名称
  • .contents 获取标签的所有子级, 返回一个list
  • .descendants 获取子孙节点
  • .parent 获取父节点
  • .next_siblings 后边的所有的兄弟节点

案例

注意: select获取是一个列表,需要通过下标取值

重点: 短时间内一定不要请求次数太多,否则会导致IP地址封禁,(可以通过time设置一下请求的时长)

XPath

XPath 是一种用于在 XML 和 HTML 文档中定位节点的查询语言。相比 BeautifulSoup 的查找方法,XPath 提供了更强大和灵活的定位能力

xpath是操作DOM树

pip install lxml

html文档与xml文档的区别

  • xml用途: 用于存储和传输数据, 其焦点是数据的内容

    • xml标签: 用户自定义,无限扩展

      实例
      <?xml version="1.0" encoding="UTF-8"?><bookstore>    <book category="fiction">        <title>Harry Potter</title>        <author>J.K. Rowling</author>        <year>2005</year>        <price currency="USD">29.99</price>    </book>    <book category="technology">        <title>Learning XML</title>        <author>Erik T. Ray</author>        <year>2003</year>        <price currency="EUR">39.95</price>    </book></bookstore>
  • HTML用途:是显示数据, 数据如何更好看地显示

常用符

表达式 说明
/ 从根节点选取(绝对路径)
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(相对路径)
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
[] 选择符合条件的节点,使用索引

通过以上方式进行获取: 返回一个列表

  • xpath节点.text

    • 获取文本内容
  • 实例
    xpath('/html/body/div/h1/text()')
    • 通过/text()获取文本内容

通配符与或

XPath 通配符可用来选取未知的 XML 元素。

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型节点
实例
//html/body/div/*  # 选择div元素的所有子元素节点​//html/body/div/@*  # 选择div元素的所有属性​/html/body//*[@class] #获取后代具有class类名的元素​/html/body/div/node() # 获取div子级的所有节点​# | 或tree.xpath('//p[@class="intro"] | //div[@class="content"]')

特殊使用

text()="" 匹配文本内容

实例
# 存在空格是无法匹配成功/html/body/a[text()="你好"] # 获取a文字为你好的标签​#  清除a标签文字的空格 进行匹配/html/body/div//a[normalize-space(text())="百度"]​# 获取对应的属性/html/body/div//a[normalize-space(text())="百度"]/@href

contains() 包含

实例
 # 获取a包含 文字为百度的标签  存在空格也没事/html/body//a[contains(text(),"百度")]​# 获取对应的属性/html/body//a[contains(text(),"百度")]/@href​# 获取a标签包含n的类名 标签/html/body//a[contains(@class,"n")]

lxml库

实例
import requestsfrom lxml import etreeimport reimport time​def spider(url):    global index    headers = {}    resp = requests.request("GET", url, headers=headers)    if resp.status_code == 200:        xml = etree.HTML(resp.text)        elements = xml.xpath('//div[@class="bot-content"]')        page_next = xml.xpath('//*[@id="__layout"]/div/div[3]/div[1]/div[4]/div/div[2]/div/div[3]/a[2]/@href')​        for ele in elements:            href = ele.xpath('./@data-href')[0]            price = ele.xpath('./div[@class="price"]//text()')[0]  # 获取价格            title = ele.xpath('./div[@class="name-pic-box"]//text()')[0]  # 获取价格            spider_msg(href, price, title)​        index = index + 1        if index < 8:            spider(page_next)​    else:        print("请求失败:", resp.status_code)    pass​​def spider_msg(href, price, title):    time.sleep(1.5)    headers = {}    resp = requests.request("GET", href, headers=headers)    if resp.status_code == 200:        xml = etree.HTML(resp.text)        ele = xml.xpath('//div[@class="price-box font12"]/div//text()')        result = "".join(ele).strip()        result = re.sub(r'\s+', "-", result)        with open("./ce.txt", "a", encoding="utf-8") as f:            f.write(f'店铺:{title}\n价格:{price}\n时间:{result}\n网址:{href}\n\n')​if __name__ == "__main__":    url = "https://www.zbj.com/fw/?es=9011"    index = 1    spider(url)
  • 查询属性条件通过[]
    • xml_doc.xpath('//div[@class="item"]')
  • 获取属性值需要通过@
    • xml_doc.xpath('//div[@class="item"]/div/a/img/@src')
  • 通过text()获取内容
    • xml_doc.xpath('//li/a[@href="link1.html"]/text()')
← Python爬虫笔记(03):正则Python爬虫笔记(05):selenium自动化 →

留言

目录