python爬虫数据解析总结

python爬虫数据解析总结

1.概述

获取数据中包含了我们需要的数据和不需要的数据,这个时候可以利用一些规则过滤数据,只保留需要的数据。

2.Xpath解析html数据

Xpath解析数据分为解析本地文件数据和解析请求返回的数据,不论解析哪种数据方法都是一样的。

2.1.基本语法

1.查询语法
# 1.路径查询
// 查询所有子孙节点,不考虑层级关系
/ 查询直接子节点

# 2.id查询
//div[@id]:查询所有包含id的div标签
//div[@id="top"]

# 3.属性查询
//@class

# 4.模糊查询
//div[contains(@id, "he")]
//div[starts-with(@id, "he")]

# 5.内容查询,text函数返回查询到的内容
//div/h1/text()

# 6.逻辑运算
//div[@id="head" and @class="s_down"]
//title | //price

2.2.Xpath解析html数据

1.安装lxml库

在使用xpath语法解析html文件前需要先安装lxml库,通过python安装。

# pip方式安装
pip install lxml
# pipenv方式安装 --dev 只安装到开发环境
pipenv install --dev lxml
2.xpath解析本地文件示例

被解析本地html文件代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>path解析HTML文件</title>
</head>
<body>
    <ul>
        <li>北京</li>
        <li>上海</li>
        <li>深圳</li>
        <li>武汉</li>
    </ul>

    <ul>
        <li>大连</li>
        <li>锦州</li>
        <li>沈阳</li>
    </ul>
</body>
</html>

xpath解析html代码


from lxml import etree

'''
     xpath可以解析本地文件和请求接口响应数据
     解析本地文件使用 etree.parse
     解析服务器响应数据 etree.HTML()
'''


# xpath 解析本地文件
tree = etree.parse('./path.html')

# 路径查询
li_list = tree.xpath('//body/ul/li')
print(li_list)

# id查询,查询有id 的li, text()函数获取标签中的内容
id_list = tree.xpath('//body/ul/li[@id]/text()')
print(id_list)

# 查询指定id值的标签内容
id_l1 = tree.xpath('//body/ul/li[@id="l1"]/text()')
print(id_l1)

# 查找id为l1的li标签的class的属性值
li = tree.xpath('//ul/li[@id="l1"]/@class')

# 查询id值包含l的li标签
li = tree.xpath('//ul/li[contains(@id, "l")]/text()')
print(li)

# 查询id的值以l开头的li标签
li_start = tree.xpath('//ul/li[starts-with(@id, "l")]/text()')
print(li_start)

# 查询id为l1和class为c1的内容
li_list = tree.xpath('//ul/li[@id="l1" and @claa="c1"]/text()')

# 查询id为l1或者id为l2内容
li_list = tree.xpath('//ul/li[@id="l1"]/text() | //ul/li[@id="l2"]/text()')

3.jsonpath解析json数据

当我们需要解析json格式数据时,需要使用jsonpath库提供的方法来解析数据。

3.1.jsonpath语法

1.jsonpath主要语法
  • $ 表示文档的根元素
  • @ 表示文档的当前元素
  • .node_name 或 [‘node_name’] 匹配下级节点
  • [index] 检索数组中的元素
  • [start🔚step] 支持数组切片语法
  • * 作为通配符,匹配所有成员
  • … 子递归通配符,匹配成员的所有子元素
  • () 使用表达式
  • ?()进行数据筛选
2.jsonpath与XPath进行比较
XpathJsonPath说明
/$文档根元素
.@当前元素
/.或[]匹配下级元素
..N/A匹配上级元素,JsonPath不支持
//..递归匹配所有下级元素
**通配符,匹配下级元素
@N/A匹配属性,JsonPath不支持
[][]根据索引获取元素,Xpath索引从1开始,JsonPath索引从0开始
|[ , ]连接操作符,将多个结果拼接成数组返回
N/A[start:end:step]数据切片操作,Xpath不支持
[]?()过滤表达式
N/A()脚本表达式,使用底层脚本引擎,Xpath不支持
()N/A分组,JsonPaht不支持

3.2.解析json数据示例

1.安装jsonpath库

我们使用jsonpath库提供的方法解析json格式数据,因此需要先安装该库。jsonpath只支持解析本地json文件,不能直接解析请求接口返回的数据,因此需求先将返回的数据保存为本地文件后再解析。

# pip方式安装
pip install jsonpath
# pipenv方式安装 --dev表示安装在开发环境
pipenv install --dev jsonpath
2.解析数据文件
{ "store": {
    "book": [
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}
3.解析示例
import json
import jsonpath

# 加载本地被解析json文件
obj = json.load(open('./json_parse.json', 'r', encoding='utf-8'))

# 获取所有图书的作者
auth_list = jsonpath.jsonpath(obj, '$.store.book[*].author')


# 获取所有作者
auth_list = jsonpath.jsonpath(obj, '$.store..author')

# 获取store下所有内容
auth_list = jsonpath.jsonpath(obj, '$.store')

# 获取store里面所有东西的price
auth_list = jsonpath.jsonpath(obj, '$.store..price')

# 获取第三本书
auth_list = jsonpath.jsonpath(obj, '$.store.book[2]')


# 获取最后一本书
auth_list = jsonpath.jsonpath(obj, '$.store.book[(@.length - 1)]')


# 获取前面的两本书
auth_list = jsonpath.jsonpath(obj, '$.store.book[0:2]')

# 过滤所有包含isbn的书
# 条件过滤需要在()的前面添加一个? 表示是否存在
auth_list = jsonpath.jsonpath(obj, '$..book[?(@.isbn)]')


# 过滤所有价格低于10的书
auth_list = jsonpath.jsonpath(obj, '$..book[?(@.price < 10)]')
print(auth_list)

3.3.解析淘票票网站json数据示例

从淘票票网站中请求接口获取所有城市数据,通过jsonpath过滤出所有的城市名称。通过这个实例可以掌握JsonPath解析请求接口返回数据完整过程。


import ssl
import urllib.request
from lxml import etree
import json
import jsonpath

# 全局取消ssl证书验证
ssl._create_default_https_context = ssl._create_unverified_context

url = 'https://dianying.taobao.com/cityAction.json?activityId&_ksTS=1666688964623_108&jsoncallback=jsonp109&action=cityAction&n_s=new&event_submit_doGetAllRegion=true'
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.8',
    'cookie': 'miid=620415126792701199; enc=bXSrNYQszBm0avcGUnaxukmiSNO4zy57XBaokxJX4IEn508D8Y8itOHbJcocQ1ocSh03xlMw%2FAQdiSheaEL5sbdUzhRjT24K8IjspKA6N1zVbhcgMb9o%2FLsj6jmEr7r1; thw=cn; cna=lnbQGjLBgTYCAXt1V9VpygAB; t=3cf604814d241312591de0f1a6c1379e; sgcookie=E100GEcD6f0H1%2BVPzQpFdecSrku8hBUGO83GUY0qL272gAo%2BJ%2FBAm%2FFat%2BWa6GI5sBiJCKa20VU8NDdHPzZrUBfFDBrQQMXCkctCbMudiJZec9WoFZP4eoGh%2FfOizxTtPVFY; tracknick=%5Cu5C0F%5Cu9B3C151; _cc_=Vq8l%2BKCLiw%3D%3D; cookie2=16a86bd0e2f35d6f8dae9a1c2d039eb0; v=0; _tb_token_=5e38e339338b; xlly_s=1; tfstk=cq5PBVVLUBjfxsQLXIAF_pzLtk-RaJfG9m8BEkb1wWm-qR92bs2SvEbAnKJsuDvl.; l=eBLUYtieLsfzGrO6BOfwhurza77tMIRAguPzaNbMiOCPOu5e5yBfW6ykk5TwCnGVhsByR3oUDdSXBeYBcC2sjqj4axom4zDmn; isg=BKWllEEcKvO0gk-3u7Fn5krjtGff4ll08NiERqeKFFzrvsUwbzPcRLpQSCLIvnEs',
    'referer': 'https://dianying.taobao.com/'
}

request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
# 通过切片去除数据中不需要的括号
content_json = content.split('(')[1].split(')')[0]

# 将请求接口响应数据保存到本地文件
with open('淘票票所有城市.json', 'w', encoding='utf-8') as fp:
    fp.write(content_json)

# 读取文件中的数据
obj = json.load(open('淘票票所有城市.json', 'r',encoding='utf-8'))
# 解析json数据,获取所有城市名称
city = jsonpath.jsonpath(obj, '$..regionName')
print(city)

4.Beautiful Soup解析HTML或XML数据

Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库,简单来说,它能将HTML的标签文件解析成树形结构,然后方便地获取到指定标签的对应属性。

BeautifulSoup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐使用lxml 解析器。

BeautifulSoup支持解析本地文件和请求响应数据

Beautiful Soup有完整的语法,可以参考中文文档使用:https://beautifulsoup.cn/

在开始之前,确保已经安装好Beautiful Soup和lxml。如果没有安装,请参考下面的安装教程。

# pip方式安装
pip install lxml
# pipenv方式安装 --dev只安装在开发环境
pipenv install --dev lxml

# pip方式安装
pip install bs4
# pipenv方式安装 --dev只安装在开发环境
pipenv install --dev bs4

4.1.Beautiful Soup基础语法使用示例

被解析html文件内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>path解析HTML文件</title>
</head>
<body>
<div>
    <ul>
        <li id="l1" class="c1">北京</li>
        <li id="l2">上海</li>
        <li>深圳</li>
        <li>武汉</li>
    </ul>

    <ul>
        <li>大连</li>
        <li>锦州</li>
        <li>沈阳</li>
    </ul>
    <span>span</span>
    <p>p</p>

</div>

</body>
</html>

Beautiful Soup解析html文件代码

from bs4 import BeautifulSoup

# 通过解析本地文件,了解bs4基础语法使用
# 默认打开文件的格式是gbk 所以在打开文件的时候指定编码格式
# BeautifulSoup解析器指定为lxml
soup = BeautifulSoup(open('path.html', encoding='utf-8'), 'lxml')

# 根据标签名称查找节点
# 查找第一个符合条件的数据
print(soup.li)

# 查找标签的属性和值
print(soup.li.attrs)

# bs4常用函数
'''
find函数:查找第一个符合条件的数据
'''
# 返回第一个符合条件的数据
print(soup.find('li'))

# 根据属性值查找标签
print(soup.find('li', id='l2'))

# 根据class属性查找标签要注意class需要添加下划线,不然就和python关键字class冲突
print(soup.find('li', class_='c1'))

'''
find_all: 查找到所有符合条件的数据
'''

# 返回是一个列表,边切返回了所有li标签
print(soup.find_all('li'))

# 如果想获取多个标签的数据,需要放到列表中
print(soup.find_all(['li', 'span']))

# 限制匹配的数量
print(soup.find_all('li', limit=2))

'''
select: 根据CSS选择器得到节点对象
'''

# select返回的是一个列表,并且返回多个数据
print(soup.select('li'))

# 可以通过.代表class类选择器,查找数据
print(soup.select('.c1'))

# #代表id选择器,查找属于
print(soup.select('#l1'))

# 属性选择器
print(soup.select('li[id]'))

# 查找li标签中id为l2的标签
print(soup.select('li[id="l2"]'))

# 层级选择器
# 后代选择器
print(soup.select('div li'))

# 父子选择器
print(soup.select('div > span'))

# 组合选择器,同时找到span和li标签
print(soup.select('span, li'))

'''
 节点选择器
'''

# 获取节点内容
# select返回的是列表,列表没有string,因此需要返回列表中某个值
obj = soup.select('#l1')[0]
# 如果标签对象中,只有内容,没有嵌套其他标签,则string和get_text()都可以拿到数据
# 如果标签对象中嵌套了标签,那么string获取不到数据,而get_text()可以获取到数据,因此建议使用get_text()函数获取标签中的数据
print(obj.string)
print(obj.get_text())

# 节点的属性
# 通过属性名称获取标签
obj = soup.select('#l1')[0]
# 输出获取到的标签名称
print(obj.name)
# 输出获取到的标签的属性,返回一个字典
print(obj.attrs)

# 通过属性名称获取属性值
print(obj.attrs.get('id'))

4.2.Beautiful Soup解析星巴克官网数据

下面通过爬取星巴克官网菜单数据,练习Beautiful Soup解析数据使用方法。


import ssl
import urllib.request
from bs4 import BeautifulSoup
# 全局取消ssl证书验证
ssl._create_default_https_context = ssl._create_unverified_context

url = 'https://www.starbucks.com.cn/menu/'

request = urllib.request.Request(url=url)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
# print(content)

soup = BeautifulSoup(content, 'lxml')

# 可以通过xpath插件获取内容,然后在转为select选择器
# //ul[@class="grid padded-3 product"]//strong/text()
name_list = soup.select('ul[class="grid padded-3 product"] strong')
for name in name_list:
    # 打印产品名称
    print(name.get_text())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值