Python爬虫基础之 解析

编程入门 行业动态 更新时间:2024-10-26 22:17:35

Python<a href=https://www.elefans.com/category/jswz/34/1770264.html style=爬虫基础之 解析"/>

Python爬虫基础之 解析

二、解析

Xpath

1.初识Xpth

1.1什么是Xpath?

XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历。

XPath定位在爬虫和自动化测试中都比较常用,通过使用路径表达式来选取 XML 文档中的节点或者节点集,熟练掌握XPath可以极大提高提取数据的效率。

1.2Xpath语法

选取节点

表达式描述
nodename选取此节点的所有子节点。
/从根节点选取(取子节点)。
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(取子孙节点)。
.选取当前节点。
选取当前节点的父节点。
@选取属性。
路径表达式结果
bookstore选取 bookstore 元素的所有子节点。
/bookstore选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book选取属于 bookstore 的子元素的所有 book 元素。
//book选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang选取名为 lang 的所有属性。

谓语

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

谓语被嵌在方括号中。

在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式结果
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position() < 3]选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=‘eng’]选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00]选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]//title选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

选取未知节点

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

通配符描述
*匹配任何元素节点。
@*匹配任何属性节点。
@*匹配任何属性节点。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式结果
/bookstore/*选取 bookstore 元素的所有子元素。
//*选取文档中的所有元素。
//title[@*]选取所有带有属性的 title 元素。

选取若干路径

通过在路径表达式中使用"|"运算符,可以选取若干个路径。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式结果
//book/title | //book/price选取 book 元素的所有 title 和 price 元素。
//title | //price选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。
1.3HTML的基本标签
标题:`<h1>、<h2>、<h3>、<h4>、<h5>、<h6>、<title>`段落:<p>链接:<a>图像:<img>样式:<style>列表:`无序列表<ul>、有序列表<ol>、列表项<li>`块:`<div>、<span>`脚本:<script>注释:<!--注释-->

2.Xpath的基本使用

2.1安装lxml库

在pycharm的设置–>项目:Python爬虫–>Python解释器 中进行安装。

2.2Xpath解析类型

(1)本地文件 etree.parse

(2)服务器响应的数据 etree.HTML(content)

2.2.1Xpath解析本地文件

本地文件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"/><title>Title</title>
</head>
<body><ul><li id="l1" class="c1">北京</li><li id="l2">上海</li><li id="c3">深圳</li><li id="c4">上海</li></ul><ul><li>大连</li><li>锦州</li><li>沈阳</li></ul></body>
</html>

解析的基本使用

from lxml import etree# xpath解析本地文件
tree = etree.parse('17_解析_xpath的基本使用.html')# tree.xpath('xpath路径')
# // 查找所有的子孙结点,不考虑层级关系
#//  找直接子节点# 查找ul下面的li
# li_list = tree.xpath('//body/ul/li')# 查找所有有id的属性的li标签
# text()获取标签中的内容
# li_list = tree.xpath('//ul/li[@id]/text()')# 找到id为l1的li标签
# li_list = tree.xpath('//ul/li[@id="l1"]/text()')# 查找到id为l1的li标签的class的属性值
# []中写标签的属性值,属性名前要有@,值用""括起来
# li = tree.xpath('//ul/li[@id="l1"]/@class')# 查询id中包含l的li标签
# li_list = tree.xpath('//ul/li[contains(@id, "l")]/text()')# 查询id的值以l开头的li标签
# li_list = tree.xpath('//ul/li[starts-with(@id, "l")]/text()')# 查询id为l1和class为c1的标签
# li_list = tree.xpath('//ul/li[@id="l1" and @class="c1"]/text()')# | (或)不能再标签之间用
li_list = tree.xpath('//ul/li[@id="l1"]/text() | //ul/li[@id="l2"]/text()')print(li_list)
print(len(li_list))
2.2.2Xpath解析服务器响应数据

例一:以获取百度网站的“百度一下”为例

import urllib.requesturl = ''headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'
}reqeust = urllib.request.Request(url=url, headers=headers)response = urllib.request.urlopen(request)content = response.read().decode('utf-8')from lxml import etree# 解析服务器响应的数据
tree = etree.HTML(content)# 获取想要的数据 xpath的返回值是一个列表类型的数据
result = tree.xpath('//input[@id="su"]/@value')[0]print(result)

例二:利用解析下载站长素材的前十页图片

import urllib.request
form lxml import etree
# 需求 下载前十页的图片
# .html
# .html
# .html# 封装请求对象定制
def create_request(page):if (page == 1):	# 因为第一页的url和其他页的不同需要单独判断url = '.html'else:url = '' + str(page) + '.html'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'}request = urllib.request.Request(url=url, headers=headers)return request# 封装获取网页内容
def get_content(request):response = urllib.request.urlopen(request)content = response.read().decode('utf-8')return contentdef down_load(content):# 下载图片	利用xpath找出图片名称以及图片的路径tree = etree.HTML(content)name_list = tree.xpath('/html/body/div[3]/div[2]/div//img/@alt')src_list = tree.xpath('/html/body/div[3]/div[2]/div/img/@data-original')for i in range(len(name_list)):name = name_list[i]src = src_list[i]url = 'https:' + srcurllib.request.urlretrieve(url=url, filename='./loveImg/' + name + '.jpg')if __name__ == '__main__':start_page = int(input('请输入起始页码:'))end_page = int(input('请输入结束页码:'))for page in range(start_page, end_page+1):# (1)请求对象的定制request = create_request(page)# (2)模拟向服务器发送数据content = get_content(request)# (3)下载down_load(content)

JsonPath

1.初识JsonPath

1.1关于JsonPath

JsonPath和JSON文档有关系,正如XPath之于XML文档一样,JsonPath为Json文档提供了解析能力,通过使用JsonPath,你可以方便的查找节点、获取想要的数据,JsonPath是Json版的XPath。

1.2JsonPath语法

​ (1)JsonPath语法要点:

  • $ 表示文档的根元素

  • @ 表示文档的当前元素

  • .node_name['node_name'] 匹配下级节点

  • [index] 检索数组中的元素

  • [start:end:step] 支持数组切片语法

  • * 作为通配符,匹配所有成员

  • .. 子递归通配符,匹配成员的所有子元素

  • (<expr>) 使用表达式

  • ?(<boolean expr>)进行数据筛选

    (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分组,JsonPath不支持

    注意:

    • JsonPath的索引从0开始计数
    • JsonPath中字符串使用单引号表示,例如:$.store.book[?(@.category=='reference')]中的'reference'

2.JsonPath的基本使用

2.1JsonPath解析本地文件

本地文件

{ "store": {"book": [{ "category": "修真","author": "六道","title": "坏蛋是怎样练成的","price": 8.95},{ "category": "修真","author": "天蚕土豆","title": "斗破苍穹","price": 12.99},{ "category": "修真","author": "唐家三少","title": "斗罗大陆","isbn": "0-553-21311-3","price": 8.99},{ "category": "修真","author": "南派三叔","title": "星辰变","isbn": "0-395-19395-8","price": 22.99}],"bicycle": {"color": "黑色","price": 19.95}}
}

代码示例

import urllib.request
import json
import jsonpath#加载本地文件
obj = json.load(open('filename'))# 获取书店下的所有作者
author_list = jsonpath.jsonpath(obj, '$.store.book[*].author')
print(author_list)# 直接利用绝对路径获取所有作者
authors_list = jsonpath.jsonpath(obj, '$..author')
print(authors_list)# 获取store下所有的元素
tag_list = jsonpath.jsonpath(obj, '$.store.*')
print(tag_list)# 获取store下所有东西的价格
price_list = jsonpath.jsonpath(obj, '$.store..price')
print(price_list)

注意:

  • json.load()参数是对象
  • json.loads()参数是字符串
2.2JaonPath解析服务器响应文件

以解析淘票票为例

import urllib.request
import jsonurl = '.json?activityId&_ksTS=1681105103837_108&jsoncallback=jsonp109&action=cityAction&n_s=new&event_submit_doGetAllRegion=true'# 经测试只需要referer即可
headers = {'referer': '/?spm=a1z21.3046609.city.1.7db2112axDN5Jc&n_s=new&city=110100',
}request = urllib.request.Request(url=url, headers=headers)response = urllib.request.urlopen(reqeust)content = response.read().decode('utf-8')#利用分隔符分割,返回的是数组,取第二个元素,即下标为1
content = content.split('(')[1].split(')')[0]#写入本地文件
with open('解析_jsonpath解析淘票票.json', 'w', encoding='utf-8') as fp:fp.write(content)obj = json.load(open('解析_jsonpath解析淘票票.json', 'r', encoding='utf-8'))city_list = jsonpath.jsonpath(obj, '$..regionName')print(city_list)

关于本例url如何获取的问题

​ f12,刷新主页,清空全部nerwork栏内容,然后鼠标点击地名会出现接口,接口中有url,为json数据内容。

注意:

  • content.split('(')'('为分割符进行分割,并以列表 形式返回

Bs4

1.初识Bs4

1.1什么是Bs4

BS4全称是Beatiful Soup,它提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为tiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。

1.2Bs4语法

在 BS4 中,通过标签名和标签属性可以提取出想要的内容

eg:

​ 获取整个p标签的html代码:soup.p

​ 获取p标签:soup.p.b

​ 获取p标签内容:soup.p.text

2.Bs4的基本使用

2.1Bs4解析本地文件

本地文件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div><ul><li id="l1">张三</li><li id="l2">李四</li><li>王五</li><a href="" id="" class="a1">尚硅谷</a></ul></div><a href="" title="a2">百度</a><div id="d1"><span>哈哈哈</span></div><p id="p1" class="p1">呵呵呵</p>
</body>
</html>

解析本地文件

from bs4 import BeautifulSoup# 默认打开文件的格式是gbk
soup = BeautifulSoup(open('解析_bs4的基本使用.html', encoding='utf-8'), 'lxml')# 根据标签名查找节点
# 找到的是第一个符合条件的数据
print(soup.a)
print(soup.a.attrs)	# attrs 获取标签的属性和属性值# bs4的一些函数
# (1)find
# 返回第一个符合条件的数据
print(soup.find('a'))
# 根据title的值找到对应的标签对象
print(soup.find('a', title="a2"))
# 根据class的值找到对应的标签对象,class需要加下划线
print(soup.find('a', class_="a1"))# (2)find_all 返回列表,并返回所有的a标签
print(soup.find_all('a'))# 如果想获取的是多个标签的数据,那么需要在参数中添加列表的数据(参数的数据类型是列表)
print(soup.find_all('['a', 'span']'))
# limit的作用,查找前几个数据
print(soup.find_all('li', limit=2))# (3) select 推荐使用
# select方法返回的是一个列表,并且返回多个数据
print(soup.select('a'))
# 可以通过 . 代表class,我们把这种操作叫做类选择器
print(soup.select('.a1'))
# 可以通过 # 代表id
print(soup.select('#l1')) # 属性选择器--通过属性来寻找对应的标签
# 查找li标签中有id的标签
print(soup.select('li[id]'))
# 查找li标签中id为l2的标签
print(soup.select('li[id="l2"]'))# 层级选择器
# 后代选择器
# 找到的是div下面的li
print(soup.select('div li'))# 子代选择器
# 某标签的第一级子标签
# 注意:很多的计算机编程语言中,如果不加空格不会输出内容,但在bs4中,不会报错,会显示内容
print(soup.select('div > ul > li'))# 找到a标签和li标签的所有对象
print(soup.select('a, li'))# 节点信息
# 获取节点信息
obj = soup.select('#d1')[0]
# 如果标签对象中只有内容,那么string和get_text()都可以使用
# 如果标签对象中除了内容还有标签,那么string就获取不到数据,而get_text()可以获取数据
# 推荐使用 get_text()
print(obj.string)	
print(obj.get_text())# 节点的属性
obj = soup.select('#p1')[0]
# name是标签的名字
print(obj.name)
# 将属性值作为一个字典返回
print(obj.attrs)# 获取节点的属性
obj = soup.select('#p1')[0]print(obj.attrs.get('class')) # 通过字典中的get()方法获取class的值
print(obj.get('class'))
print(obj['class'])
2.1Bs4解析服务器响应文件

以爬取星巴克数据为例

import urllib.request
from bs4 import BeautifulSoupurl = ''response = urllib.request.urlopen(url)content = response.read().decode('utf-8')soup = BeautifulSoup(content, 'lxml')# //ul[@class="grid padded-3 product"]//strong/text()
# name_list = soup.select('.grid padded-3 product') 错误的
name_list = soup.select('ul[class="grid padded-3 product"] strong')
# print(name_list)for name in name_list:# print(name.string)print(name.get_text())

更多推荐

Python爬虫基础之 解析

本文发布于:2024-02-10 13:50:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1675761.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:爬虫   基础   Python

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!