爬虫!Python爬虫!

什么是爬虫:网络爬虫也叫网络蜘蛛,如果把互联网比喻成一个蜘蛛网,那么蜘蛛就是在网上爬来爬去 的蜘蛛,爬虫程序通过请求url地址,根据响应的内容进行解析采集数据

简单来说就是用代码模拟人的行为,去各各网站溜达、点点按钮、查查数据。或者把看到的数据拿下来。

爬虫应用领域:   

  • 批量采集某个领域的招聘数据,对某个行业的招聘情况进行分析
  • 批量采集某个行业的电商数据,以分析出具体热销商品,进行商业决策 • 采集目标客户数据,以进行后续营销
  • 批量爬取腾讯动漫的漫画,以实现脱网本地集中浏览
  • 开发一款火车票抢票程序,以实现自动抢票
  • 爬取评论,舆情监控
  • 爬取说说信息,分析上线时间

爬虫有合法和非法之分:

合法的爬虫

  • 公开的数据,没有标识不可爬取
  • 不影响别人服务器
  • 不影响的业务

不合法的爬虫

  • 用户数据

  • 部分网站、APP数据超过指定数量

  • 明文规定不让爬取

    • 在域名后加上/robots.txt查看
    • 页面上标明
  • 影响业务

  • 影响服务器

    类似DDOS攻击的问题

反爬:有时企业不想自己的数据被别人拿到。这时就会设置反爬的手段,来不让爬虫获取数据。

反爬虫常用一些手段:

  • 合法检测:请求校验(useragent,referer,接口加签 ,等)
  • 验证码:识别文字、做题、滑动等
  • 小黑屋:IP/用户限制请求频率,或者直接拦截
  • 投毒:反爬虫高境界可以不用拦截,拦截是一时的,投毒返回虚假数据,可以误导竞品决策

爬虫基本套路:

  • 基本流程

    • 目标数据:想要什么数据

    • 来源地址:URL

    • 结构分析

      • 具体数据在哪(网站、还是APP)
      • 如何展示的数据
    • 实现构思

    • 操刀编码

  • 基本手段

    • 破解请求限制

      • 请求头设置,如:useragant为有效客户端
      • 控制请求频率(根据实际情景)
      • IP代理:PORT
      • 签名/加密参数从html/cookie/js分析
    • 破解登录授权

      • 请求带上用户cookie信息
    • 破解验证码

      • 简单的验证码可以使用识图读验证码第三方库
  • 解析数据

    • HTML Dom解析

      • 正则匹配,通过的正则表达式来匹配想要爬取的数据,如:有些数据不是在html 标签里,而是在html的script 标签的js变量中
      • 使用第三方库解析html dom,比较喜欢类jquery的库
    • 数据字符串

      • 正则匹配(根据情景使用)
      • 转 JSON/XML 对象进行解析
  • 网页抓包工具:浏览器开发者工具 -->> F12
    • 以Google浏览器为例:

第一个简单爬虫程序:(以百度网站为例)

from urllib.request import urlopen
 
response = urlopen("http://www.baidu.com/")
print(response.read().decode())

模块一:requests

requests模块学习文档文档链接:requests模块文档

python安装:

pip install requests==2.32.3

requests基本请求:

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")

例子:

import requests
url = "https://www.baidu.com"
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.475.400 QQBrowser/13.5.6267.400'}
resp = requests.get(url, headers=headers)

print(resp.text[:111])
# print(resp.json())
# print(resp.content)

获取响应信息

代码含义
resp.json()获取响应内容(以json字符串)
resp.text获取响应内容 (以字符串)
resp.content获取响应内容(以字节的方式)
resp.encoding获取网页编码
resp.headers获取响应头内容
resp.request.headers请求头内容
resp.url获取访问地址
resp.cookie

获取cookie

request请求方式:
        1: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)

        2: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 login():
    url = "http://localhost:8000/playground/login"
    data = {
        'uname':'admin',
        'password':'123456'
    }
    # headers = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36"
    resp = requests.post(url, data=data)
    print(resp.text)

def get_cookie():
    url = 'http://localhost:8000/playground/user_info'
    cookie = {
        'session':'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTczODkyMzMxNH0.UVGQCVHASi7XWIH_WNuLgq1xMN6PTkTqeiPO6bbWxZQ',
        'Max-Age':'600',
        'Path':'/'
    }
    cookie1 = ''
    resp = requests.get(url,cookies=cookie)
    print(resp.text)

def get_cookies():
    url = "http://localhost:8000/playground/user_info"
    cookie = "session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTczODkyMzMxNH0.UVGQCVHASi7XWIH_WNuLgq1xMN6PTkTqeiPO6bbWxZQ"
    headers = {
        'cookie':cookie
    }
    resp = requests.get(url, headers=headers)
    print(resp.text)
if __name__ == '__main__':
    # login()
    get_cookie()

爬虫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] = value
  resp = 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()
​
​
  '''
   使用cookie
   1. 直接手动从浏览器复制,放到请求对象中
   2. 将cookie保存到本地,下次登录时,直接读取本地文件
   3. 使用session对象,自动保存cookie,连续性请求
   '''

爬虫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()

v

正则表达式

正则表达式:是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

正则表达式在线测试|菜鸟工具

规则:

定位符:

字符描述
^匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n 或 \r 之后的位置匹配。
$匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配。
\b匹配一个单词边界,即字与空格间的位置。
\B非单词边界匹配。

注意不能将限定符和定位符一起使用
普通字符:
字符描述
[ABC]匹配 [...] 中的所有字符,例如 [aeiou] 匹配字符串 "google runoob taobao" 中所有的 e o u a 字母
[^ABC]匹配除了 [...] 中字符的所有字符,例如 [^aeiou] 匹配字符串 "google runoob taobao" 中除了 e o u a 字母的所有字母
[A-Z][A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母
.匹配除换行符(\n、\r)之外的任何单个字符,相等于 [^\n\r]
[\s\S]匹配所有。\s 是匹配所有空白符,包括换行,\S 非空白符,不包括换行
\w匹配字母、数字、下划线。等价于 [A-Za-z0-9_]
特殊字符:
特别字符描述
( )标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和 )。
[标记一个中括号表达式的开始。要匹配 [,请使用 \[
?匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
\将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\' 匹配 "",而 '(' 则匹配 "("。
{ 标记限定符表达式的开始。要匹配 {,请使用 \{
|指明两项之间的一个选择。要匹配 |,请使用 \|
非打印字符:
字符描述
\cx匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\f匹配一个换页符。等价于 \x0c 和 \cL
\n匹配一个换行符。等价于 \x0a 和 \cJ。
\r匹配一个回车符。等价于 \x0d 和 \cM
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。
\S匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\t匹配一个制表符。等价于 \x09 和 \cI
\v匹配一个垂直制表符。等价于 \x0b 和 \cK
限定符:
字符描述
*匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
?匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。
{n}n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,}n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
数量词的 贪婪模式非贪婪模式

正则表达式通常用于在文本中查找匹配的字符串 Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;

非贪婪的则相反,总是尝试匹配尽可能少的字符

例如:正则表达式”ab”如果用于查找”abbbc”,将找到”abbb”。而如果使用非贪婪的数量词”ab?”,将找到”a”


正则表达式修饰符(可选标志)
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符描述
re.I使匹配对大小写不敏感
re.L做本地化识别(locale-aware)匹配
re.M使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾
re.S使 . 匹配包括换行在内的所有字符
re.U根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解
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.baidu.com">百度/a></div></html>'
tf = re.findall('<a href="(.+)">',info)
tf2 = re.findall('<a href=".+">(.+)</a>',info)
print(tf2)

数据解析-Beautiful Soup的使用

Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序

Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,仅仅需要说明一下原始编码方式就可以了

BS4学习文档

python安装:

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语言库
html5libBeautifulSoup(markup, “html5lib”)1. 最好的容错性 2.以浏览器的方式解析文档 3.生成HTML5格式的文档 4.速度慢不依赖外部扩展

创建Beautiful Soup对象:
from bs4 import BeautifulSoup
​
bs = BeautifulSoup(html,"lxml")

BS将复杂HTML文档转换成一个复杂的树型结构,每个节点都是Python对象,所有对象可以归纳为三种: 

  • Tag
  • NavigableString
  • Comment

HTML例子:

<title>百度</title>
<div class='info' float='left'>Welcome to baidu</div>
<div class='info' float='right'>
  <span>Good Good Study</span>
  <a href='www.baidu.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)

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的元素

 

 数据解析-xpath的使用

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上

XPATH官网

XPATH教程

python安装Xpath:

pip install lxml==5.3.0

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 + 410
减法6 – 42
*乘法6 * 424
div除法8 div 42
=等于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。
orprice=9.80 or price=9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
andprice>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
mod计算除法的余数5 mod 21
选择XML文件中的节点:
  • element(元素节点)
  • attribute(属性节点)
  • text() (文本节点)
  • concat(元素节点,元素节点)
  • comment (注释节点)
  • root (根节点)

XPath工具:

浏览器-F12-元素-CTRL+F

浏览器-控制台-$x(表达式)

Xpath helper (安装包需要科学上网)

【在获取Xpath helper时可能会遇到出现程序包无效的问题】

方法:使用修改安装包的后缀名为 rar,解压文件到一个文件夹,再用加载文件夹的方式安装即可

JSON数据使用 

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。

同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互

JSON和XML的比较可谓不相上下

Python 中自带了JSON模块,直接import json就可以使用了

Json数据官方学习文档

Json在线解析网站

json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构

  1. 对象:对象在js中表示为{ }括起来的内容,数据结构为 { key:value, key:value, ... }的键值对的结构。

    在面向对象的语言中,key为对象的属性,value为对应的属性值。

    取值方法为 对象.key 获取属性值,这个属性值的类型可以是数字、字符串、数组、对象这几种

  2. 数组:数组在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.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.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.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。

官方文档:JsonPath官方文档

Python安装:

pip install jsonpath==0.82.2

JsonPath与XPath语法对比:

XPathJSONPath描述
/$根节点
.@当前节点
/.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表达式要从$开头

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ST_小罗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值