Python爬虫基础与应用
目录
爬虫介绍
什么是爬虫?
爬虫有什么作用?
爬虫应用领域
业界的情况如何
爬虫的合法性
合法的爬虫
不合法的爬虫
反爬与反反爬
爬虫的基本套路
选择一门语言
浏览器- 开发者工具
爬虫靶场
访问方式
第一个爬虫
数据来源
小试牛刀
requests模块-请求方式
文档地址
安装
基本请求
获取响应信息
requests模块-请求方式
Form表单
Json参数
代码
爬虫Token的使用
Token的使用场景
代码
数据的格式
Python使用正则
常用方法
正则表达式实战
数据解析-Beautiful Soup的使用
简介
Beautiful Soup 安装
创建 Beautiful Soup 对象
三大对象种类
Tag
获取属性
Comment
数据解析-Beautiful Soup方法的使用
find_all() 搜索文档树
字符串
正则表达式
列表
keyword
True
按CSS搜索
按属性的搜索
CSS选择器
BS4实战
数据解析-xpath的使用
介绍
XPath语法
节点的关系
常用的路径表达式
通配符
选取若干路径
谓语
运算符
选择XML文件中节点:
XPath工具
安装
JSON数据使用
Python中的json模块
json.loads()
json.dumps()
json.dump()
json.load()
注意事项
JsonPath的使用
安装
JsonPath与XPath语法对比
代码
爬虫介绍
什么是爬虫?
网络爬虫也叫网络蜘蛛,如果把互联网比喻成一个蜘蛛网,那么蜘蛛就是在网上爬来爬去 的蜘蛛,爬虫程序通过请求url地址,根据响应的内容进行解析采集数据
简单的说:就是用代码模拟人的行为,去各各网站溜达、点点按钮、查查数据。或者把看到的数据拿下来。
爬虫有什么作用?
通过有效的爬虫手段批量采集数据,可以降低人工成本,提高有效数据量,给予运营/销售的数据支撑,加快产品发展。
爬虫应用领域
- 批量采集某个领域的招聘数据,对某个行业的招聘情况进行分析
- 批量采集某个行业的电商数据,以分析出具体热销商品,进行商业决策 • 采集目标客户数据,以进行后续营销
- 批量爬取腾讯动漫的漫画,以实现脱网本地集中浏览
- 开发一款火车票抢票程序,以实现自动抢票
- 爬取评论,舆情监控
- 爬取说说信息,分析上线时间
- ...
业界的情况如何
目前互联网产品竞争激烈,业界大部分都会使用爬虫技术对竞品产品的数据进行挖掘、采集、大数据分析,这是必备手段,并且部分公司都设立了爬虫工程师
的岗位
爬虫的合法性
民间流传出下面一段话:
爬虫爬得欢,监狱要坐穿; 数据玩的溜,牢饭吃个够
问题
爬虫是否是合法的呢?
答案
有时合法,有时不合法,因情况而定
爬虫是利用程序进行批量爬取网上的公开信息,也就是前端显示的数据信息。因为信息是完全公开的,所以是常规合法的!!!
合法的爬虫
- 公开的数据,没有标识不可爬取
- 不影响别人服务器
- 不影响的业务
不合法的爬虫
-
用户数据
-
部分网站、APP数据超过指定数量
-
明文规定不让爬取
- 在域名后加上
/robots.txt
查看 - 页面上标明
- 在域名后加上
-
影响业务
-
影响服务器
类似DDOS攻击的问题
提示
部分爬虫虽然违法,但公司、或企业不会直接报警。会采用反爬的手段,严重后才会报警
反爬与反反爬
反爬:有时企业不想自己的数据被别人拿到。这时就会设置反爬的手段,来不让爬虫获取数据。
反爬虫常用一些手段:
- 合法检测:请求校验(useragent,referer,接口加签 ,等)
- 验证码:识别文字、做题、滑动等
- 小黑屋:IP/用户限制请求频率,或者直接拦截
- 投毒:反爬虫高境界可以不用拦截,拦截是一时的,投毒返回虚假数据,可以误导竞品决策
- ... ...
反反爬:破解掉反爬手段,再获取其数据。所有的手段都能破解吗?
道高一尺魔高一丈,这是一场没有硝烟的战争,程序员VS程序员
爬虫的基本套路
-
基本流程
-
目标数据:想要什么数据
-
来源地址
-
结构分析
- 具体数据在哪(网站、还是APP)
- 如何展示的数据
-
实现构思
-
操刀编码
-
-
基本手段
-
破解请求限制
- 请求头设置,如:useragant为有效客户端
- 控制请求频率(根据实际情景)
- IP代理
- 签名/加密参数从html/cookie/js分析
-
破解登录授权
- 请求带上用户cookie信息
-
破解验证码
- 简单的验证码可以使用识图读验证码第三方库
-
-
解析数据
-
HTML Dom解析
- 正则匹配,通过的正则表达式来匹配想要爬取的数据,如:有些数据不是在html 标签里,而是在html的script 标签的js变量中
- 使用第三方库解析html dom,比较喜欢类jquery的库
-
数据字符串
- 正则匹配(根据情景使用)
- 转 JSON/XML 对象进行解析
-
选择一门语言
爬虫可以用各种语言写, C++, Java都可以, 为什么要Python?
- 简单
- 高效
- 三方模块库多
浏览器- 开发者工具
对于爬虫来说,最核心的就是发送请求,让网络服务器返回相应的数据。而最为核心之一就是找到URL,这时就需要一个可以帮助我们分析URL的工具,浏览器开发者工具
爬虫靶场
爬虫靶场的主要作用:
-
学习和练习
- 为开发者提供一个安全的环境来练习网页爬虫技术
- 可以测试不同的爬虫策略和技术,而不用担心影响真实网站
- 适合新手学习基础爬虫概念和技术
-
测试和调试
- 可以测试爬虫程序在各种场景下的表现
- 帮助开发者发现和解决爬虫代码中的问题
- 验证爬虫的稳定性和可靠性
通过使用爬虫靶场,开发者可以:
- 在安全的环境中提升爬虫开发技能
- 为实际项目积累经验和最佳实践
访问方式
-
直接访问
http://58.87.96.193:8000/
-
docker 部署,具体步骤如下:
# 下载docker镜像
docker pull registry.cn-hangzhou.aliyuncs.com/bz_python/scrapy_center:0.1
# 创建容器,启动爬虫靶场
docker run -d -p 8000:8000 -p 3306:3306 --name scrapecenter 0bd5
第一个爬虫
数据来源
- 网站
- 移动端
小试牛刀
怎样扒网页呢?
其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它是一段HTML代码,加 JS、CSS。如果把网页比作一个人,那么HTML便是他的骨架,JS便是他的肌肉,CSS便是它的衣服。所以最重要的部分是存在于HTML
- HTML 70%
- JS 20%
- CSS 10%
爬取页面,代码如下:
from urllib.request import urlopenresponse = urlopen("http://www.baidu.com/")
print(response.read().decode())
注意
urllib模块库是python自带的。在Python2叫urllib2
真正的程序就两行,执行如下命令查看运行结果,感受一下
看,这个网页的源码已经被我们扒下来了,是不是很酸爽?
requests模块-请求方式
文档地址
https://requests.readthedocs.io/
安装
利用 pip 安装
pip install requests==2.32.3
基本请求
req = requests.get("http://www.baidu.com")
req = requests.post("http://www.baidu.com")
req = requests.put("http://www.baidu.com")
req = requests.delete("http://www.baidu.com")
req = requests.head("http://www.baidu.com")
req = requests.options("http://www.baidu.com")
获取响应信息
代码 | 含义 |
---|---|
resp.json() | 获取响应内容(以json字符串) |
resp.text | 获取响应内容 (以字符串) |
resp.content | 获取响应内容(以字节的方式) |
resp.encoding | 获取网页编码 |
resp.headers | 获取响应头内容 |
resp.request.headers | 请求头内容 |
resp.url | 获取访问地址 |
resp.cookie | 获取cookie |
requests模块-请求方式
Form表单
import requests
def form_post():# 请求地址url='http://localhost:8000/playground/add_role1'# 定义请求参数form_data = {'name':'孙权','book':'三国'}# 发送请求resp = requests.post(url,data=form_data)# 获取响应数据print(resp.text)
Json参数
def json_post():url ="http://localhost:8000/playground/add_role2"json_data = {'name':'典韦','book':'三国'}resp = requests.post(url,json=json_data)print(resp.text)
爬虫cookie的保存与使用
代码
保存与使用
import requests
def get_cookies():url = 'http://localhost:8000/playground/login'data = {'uname':'admin','password':'123456'}s= requests.Session()resp = s.post(url,data=data)
with open('cookies.txt','w') as f:for key,value in s.cookies.items():f.write(f'{key}:{value}\n')
def use_cookies():url = 'http://localhost:8000/playground/user_info'cookies = {}with open('cookies.txt','r') as f:for line in f.readlines():key,value = line.strip().split(':')cookies[key] = valueresp = requests.get(url,cookies=cookies)print(resp.text)
if __name__ == '__main__':get_cookies()use_cookies()
自动保持Cookie
import requests
def login():url = 'http://localhost:8000/playground/login'form_data ={'uname':'admin','password':'123456'}# 获取可以保存cookie的请求对象s = requests.Session()login_resp = s.post(url,data=form_data)# print(login_resp.text)url = 'http://localhost:8000/playground/user_info'info_resp = s.get(url)print(info_resp.text)
if __name__ == '__main__':login()
'''使用cookie1. 直接手动从浏览器复制,放到请求对象中2. 将cookie保存到本地,下次登录时,直接读取本地文件3. 使用session对象,自动保存cookie,连续性请求'''
爬虫Token的使用
Token的基本概念是一种常见的HTTP认证方案,它使用安全令牌来进行身份验证。当服务器响应登录请求时,通常会生成这个token。
Token的使用场景
- API接口认证
- 需要登录的网站爬取
- 受保护资源的访问
注意
Token有效期:很多token都有过期时间,需要及时更新
代码
import requests
def login():url = 'http://localhost:8000/playground/login2'json_data ={'uname':'admin','password':'123456'}resp = requests.post(url,json=json_data)token = resp.json().get('access_token')
user_url = 'http://localhost:8000/playground/user_info2'resp = requests.get(user_url,headers={'Authorization':'Bearer '+token})print(resp.text)
if __name__ == '__main__':login()
数据的格式
- HTML
- JSON
- 纯字符串
- 2进制
Python使用正则
常用方法
-
re.match(pattern, string, flags=0)
- re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
-
re.search(pattern, string, flags=0)
- re.search 扫描整个字符串并返回第一个成功的匹配。
-
re.findall(pattern,string,flags=0)
- re.findall 查找全部
-
re.sub(pattern,replace,string)
- re.sub 替换字符串
import re
str ='I study python3.10 every_day'
print('----------------------match(规则,内容)-----------------------------') # 从头开始匹配,如果匹配上了返回值,如果匹配不上,返回none
m1 = re.match('I',str)
m2 = re.match('\w',str)
m3 = re.match('\S',str)
m4 = re.match('\D',str)
m5 = re.match('I (study)',str)
m6 = re.match('\w\s(\w*)',str)
print(m6.group(1))
print('----------------------search(规则,内容)-----------------------------') # 从任意位置开始匹配,,如果匹配上了返回值,如果匹配不上,返回none
s1 = re.search('I',str)
s2 = re.search('study',str)
s3 = re.search('p\w+',str)
s4 = re.search('p\w+.\d+',str)
print(s4.group())
print('----------------------findall(规则,内容)-----------------------------') # 从任意位置开始匹配,返回所有匹配的数据,如果没有匹配内容,返回一个空列表
f1 = re.findall('ddy',str)
print(f1)
print('----------------------sub(规则,替换的内容,内容)-----------------------------') # 替换原来的数据,并返回一个新的字符串,不会修改原来的字符串
print(re.sub('p\w+','Python',str))
print(str)
print('----------------------test()-----------------------------')
info = '<html><div><a href="http://www.itbaizhan.cn">百战程序员</a></div></html>'
tf = re.findall('<a href="(.+)">',info)
tf2 = re.findall('<a href=".+">(.+)</a>',info)
print(tf2)
正则表达式实战
import re # python内置
import requests # 三方模块
# 访问的地址
url = 'http://localhost:8000/playground/1'
# 发送请求
resp = requests.get(url)
# 提取数据
title = re.findall('<h3 class="cyber-title">(.+?)</h3>',resp.text)
print(title)
sub_title = re.findall('<h5>(.+?)</h5>',resp.text)
print(sub_title)
content = re.findall('<p>(.+?)</p>',resp.text)
print(content)
info = re.findall('<p class="article-text.*?">(.+?)</p>',resp.text)
print(info)
数据解析-Beautiful Soup的使用
简介
Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序
Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,仅仅需要说明一下原始编码方式就可以了
Beautiful Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度
官网http://beautifulsoup.readthedocs.io/zh_CN/latest/
Beautiful Soup 安装
pip install beautifulsoup4
pip install bs4
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装
pip install lxml
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(markup, “html.parser”) | 1. Python的内置标准库 2. 执行速度适中 3.文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup, “lxml”) | 1. 速度快 2.文档容错能力强 | 需要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup, [“lxml”, “xml”]) BeautifulSoup(markup, “xml”) | 1. 速度快 2.唯一支持XML的解析器 3.需要安装C语言库 | |
html5lib | BeautifulSoup(markup, “html5lib”) | 1. 最好的容错性 2.以浏览器的方式解析文档 3.生成HTML5格式的文档 4.速度慢 | 不依赖外部扩展 |
创建 Beautiful Soup 对象
from bs4 import BeautifulSoup
bs = BeautifulSoup(html,"lxml")
三大对象种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
- Tag
- NavigableString
- Comment
案例代码
<title>尚学堂</title>
<div class='info' float='left'>Welcome to SXT</div>
<div class='info' float='right'><span>Good Good Study</span><a href='www.bjsxt.cn'></a><strong><!--没用--></strong>
</div>
Tag
通俗点讲就是 HTML 中的一个个标签
例如:<div>
<title>
#以lxml方式解析
soup = BeautifulSoup(info, 'lxml')
print(soup.title)
# <title>尚学堂</title>
注意
相同的标签只能获取第一个符合要求的标签
获取属性
#获取所有属性
print(soup.title.attrs)
#class='info' float='left'
#获取单个属性的值
print(soup.div.get('class'))
print(soup.div['class'])
print(soup.a['href'])
#info
NavigableString获取内容
print(soup.title.string)
print(soup.title.text)
#尚学堂
Comment
Comment 对象是一个特殊类型的 NavigableString 对象,其实输出的内容仍然不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦
if type(soup.strong.string) == Comment:print(soup.strong.prettify())
else:print(soup.strong.string)
数据解析-Beautiful Soup方法的使用
find_all() 搜索文档树
Beautiful Soup定义了很多搜索方法,这里着重介绍find_all() 其它方法的参数和用法类似
字符串
传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容
#返回所有的div标签
print(soup.find_all('div'))
正则表达式
传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容
#返回所有的div标签
print (soup.find_all(re.compile("^div")))
列表
传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回
#返回所有匹配到的span a标签
print(soup.find_all(['span','a']))
keyword
传入一个id 的参数,Beautiful Soup会搜索每个tag的”id”属性
#返回id为welcom的标签
print(soup.find_all(id='welcome'))
True
True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
按CSS搜索
传入一个css,通过 class_ 参数搜索有指定CSS类名的tag
# 返回class等于info的div
print(soup.find_all('div',class_='info'))
按属性的搜索
soup.find_all("div", attrs={"class": "info"})
CSS选择器
soup.select(参数)
表达式 | 说明 |
---|---|
tag | 选择指定标签 |
* | 选择所有节点 |
#id | 选择id为container的节点 |
.class | 选取所有class包含container的节点 |
li a | 选取所有li下的所有a节点 |
ul + p | (兄弟)选择ul后面的第一个p元素 |
div#id > ul | (父子)选取id为id的div的第一个ul子元素 |
table ~ div | 选取与table相邻的所有div元素 |
a[title] | 选取所有有title属性的a元素 |
a[class=”title”] | 选取所有class属性为title值的a |
a[href*=”sxt”] | 选取所有href属性包含sxt的a元素 |
a[href^=”http”] | 选取所有href属性值以http开头的a元素 |
a[href$=”.png”] | 选取所有href属性值以.png结尾的a元素 |
input[type="redio"]:checked | 选取选中的hobby的元素 |
BS4实战
# pip install bs4==4.12.3
# pip install lxml==5.3.0
import requests
from bs4 import BeautifulSoup
# 访问地址
url = 'http://localhost:8000/playground/1'
# 发送请求,获取响应
resp = requests.get(url)
# 创建bs4对象
bs = BeautifulSoup(resp.text,'lxml')
# 提取数据
title = bs.select('h3')
for t in title:print(t.text)
# 获取子标题
sub_title = bs.select('h5')
for s in sub_title:print(s.text)
# 获取子内容
content = bs.select('div.cyber-card > p')
for c in content:print(c.text)
# 获取段落信息
info = bs.select('p.article-text')
for i in info:print(i.text)
数据解析-xpath的使用
介绍
之前 BeautifulSoup 的用法,这个已经是非常强大的库了,不过还有一些比较流行的解析库,例如 lxml,使用的是 Xpath 语法,同样是效率比较高的解析方法。如果大家对 BeautifulSoup 使用不太习惯的话,可以尝试下 Xpath
官网 http://lxml.de/index.html
w3c http://www.w3school.com.cn/xpath/index.asp
XPath语法
XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上
节点的关系
- 父(Parent)
- 子(Children)
- 同胞(Sibling)
- 先辈(Ancestor)
- 后代(Descendant)
常用的路径表达式
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
通配符
XPath 通配符可用来选取未知的 XML 元素。
通配符 | 描述 | 举例 | 结果 |
---|---|---|---|
* | 匹配任何元素节点 | xpath('div/*') | 获取div下的所有子节点 |
@ | 匹配任何属性节点 | xpath('div[@*]') | 选取所有带属性的div节点 |
node() | 匹配任何类型的节点 |
选取若干路径
通过在路径表达式中使用“|”运算符,您可以选取若干个路径
表达式 | 结果 |
---|---|
xpath('//div| //table') | 获取所有的div与table节点 |
谓语
谓语被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点
表达式 | 结果 |
---|---|
xpath('/body/div[1]') | 选取body下的第一个div节点 |
xpath('/body/div[last()]') | 选取body下最后一个div节点 |
xpath('/body/div[last()-1]') | 选取body下倒数第二个节点 |
xpath('/body/div[positon()<3]') | 选取body下前两个div节点 |
xpath('/body/div[@class]') | 选取body下带有class属性的div节点 |
xpath('/body/div[@class="main"]') | 选取body下class属性为main的div节点 |
xpath('/body/div[price>35.00]') | 选取body下price元素大于35的div节点 |
运算符
运算符 | 描述 | 实例 | 返回值 |
---|---|---|---|
计算两个节点集 | //book | //cd | |
+ | 加法 | 6 + 4 | 10 |
– | 减法 | 6 – 4 | 2 |
* | 乘法 | 6 * 4 | 24 |
div | 除法 | 8 div 4 | 2 |
= | 等于 | price=9.80 | 如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。 |
!= | 不等于 | price!=9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。 |
< | 小于 | price<9.80 | 如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。 |
<= | 小于或等于 | price<=9.80 | 如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。 |
> | 大于 | price>9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。 |
>= | 大于或等于 | price>=9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。 |
or | 或 | price=9.80 or price=9.70 | 如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。 |
and | 与 | price>9.00 and price<9.90 | 如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。 |
mod | 计算除法的余数 | 5 mod 2 | 1 |
选择XML文件中节点:
- element(元素节点)
- attribute(属性节点)
- text() (文本节点)
- concat(元素节点,元素节点)
- comment (注释节点)
- root (根节点)
XPath工具
浏览器-元素-Ctrl+F
浏览器-控制台-$x(表达式)
Xpath helper (安装包需要科学上网)
问题
使用离线安装包 出现 程序包无效
解决方案
使用修改安装包的后缀名为 rar,解压文件到一个文件夹,再用加载文件夹的方式安装即可
安装
python若使用需要安装lxml模块
pip install lxml==5.3.0
JSON数据使用
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。
同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互
JSON和XML的比较可谓不相上下
Python 中自带了JSON模块,直接import json
就可以使用了
官方文档:http://docs.python.org/library/json.html
Json在线解析网站:http://www.json.cn/#
json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构
-
对象:对象在js中表示为{ }括起来的内容,数据结构为 { key:value, key:value, ... }的键值对的结构。
在面向对象的语言中,key为对象的属性,value为对应的属性值。
取值方法为 对象.key 获取属性值,这个属性值的类型可以是数字、字符串、数组、对象这几种
-
数组:数组在js中是中括号[ ]括起来的内容,数据结构为 ["Python", "javascript", "C++", ...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种
Python中的json模块
json模块提供了四个功能:
- dumps
- dump
- loads
- load
json.loads()
把Json格式字符串解码转换成Python对象 从json到python的类型转化对照如下:
import json
strList = '[1, 2, 3, 4]'
strDict = '{"city": "北京", "name": "范爷"}'
json.loads(strList)
# [1, 2, 3, 4]
json.loads(strDict) # json数据自动按Unicode存储
# {u'city': u'\u5317\u4eac', u'name': u'\u5927\u732b'}
json.dumps()
实现python类型转化为json字符串,返回一个str对象 把一个Python对象编码转换成Json字符串
从python原始类型向json类型的转化对照如下:
import json
listStr = [1, 2, 3, 4]
tupleStr = (1, 2, 3, 4)
dictStr = {"city": "北京", "name": "范爷"}
json.dumps(listStr)
# '[1, 2, 3, 4]'
json.dumps(tupleStr)
# '[1, 2, 3, 4]'
# 注意:json.dumps() 序列化时默认使用的ascii编码
# 添加参数 ensure_ascii=False 禁用ascii编码,按utf-8编码
json.dumps(dictStr)
# '{"city": "\\u5317\\u4eac", "name": "\\u5927\\u5218"}'
print(json.dumps(dictStr, ensure_ascii=False))
# {"city": "北京", "name": "范爷"}
json.dump()
将Python内置类型序列化为json对象后写入文件
import json
listStr = [{"city": "北京"}, {"name": "范爷"}]
json.dump(listStr, open("listStr.json","w"), ensure_ascii=False)
dictStr = {"city": "北京", "name": "范爷"}
json.dump(dictStr, open("dictStr.json","w"), ensure_ascii=False)
json.load()
读取文件中json形式的字符串元素 转化成python类型
import json
strList = json.load(open("listStr.json"))
print(strList)
# [{u'city': u'\u5317\u4eac'}, {u'name': u'\u5927\u5218'}]
strDict = json.load(open("dictStr.json"))
print(strDict)
# {u'city': u'\u5317\u4eac', u'name': u'\u5927\u5218'}
注意事项
-
json.loads() 是把 Json格式字符串解码转换成Python对象,如果在json.loads的时候出错,要注意被解码的Json字符的编码。 如果传入的字符串的编码不是UTF-8的话,需要指定字符编码的参数 encoding
data_dict = json.loads(jsonStrGBK);
dataJsonStr是JSON字符串,假设其编码本身是非UTF-8的话而是GBK 的,那么上述代码会导致出错,改为对应的:
data_dict = json.loads(jsonStrGBK, encoding="GBK");
如果 dataJsonStr通过encoding指定了合适的编码,但是其中又包含了其他编码的字符,则需要先去将dataJsonStr转换为Unicode,然后再指定编码格式调用json.loads()
dataJsonStrUni = dataJsonStr.decode("GB2312");
dataDict = json.loads(dataJsonStrUni, encoding="GB2312");
JsonPath的使用
JsonPath 是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括:Python,Javascript, PHP 和 Java。
JsonPath 对于 JSON 来说,相当于 XPATH 对于 XML。
安装
pip install jsonpath==0.82.2
官方文档:http://goessner.net/articles/JsonPath
JsonPath与XPath语法对比
Json结构清晰,可读性高,复杂度低,非常容易匹配,下表中对应了XPath的用法
XPath | JSONPath | 描述 |
---|---|---|
/ | $ | 根节点 |
. | @ | 当前节点 |
/ | . or[] | 取子节点 |
.. | n/a | 取父节点,Jsonpath未支持 |
// | .. | 就是不管位置,选择所有符合条件的条件 |
* | * | 匹配所有元素节点 |
@ | n/a | 根据属性访问,Json不支持,因为Json是个Key-value递归结构,不需要。 |
[] | [] | 迭代器标示(可以在里边做简单的迭代操作,如数组下标,根据内容选值等) |
| | [,] | 支持迭代器中做多选。 |
[] | ?() | 支持过滤操作. |
n/a | () | 支持表达式计算 |
() | n/a | 分组,JsonPath不支持 |
代码
# pip install jsonpath==0.82.2
from jsonpath import jsonpath
import requests
# 访问地址
url = 'http://localhost:8000/api/movies?page=1&movie_type=&movie_time='
resp = requests.get(url)
# 获取json的响应结果
data = resp.json()
# 提取数据
movie_title = jsonpath(data,'$..movie_name')
movie_type = jsonpath(data,'$..movie_type')
for title,type in zip(movie_title,movie_type):print(title,'=====',type)
# 注意:jsonpath表达式要从$开头