【2】Python爬虫:分析AJAX传递的JSON获取数据-初步分析动态网页(1)

2023-11-11

前言

这是本人写的第二篇文章。希望能够帮助到一些和我一样的python爬虫初学者。

在第一篇文章中,我总结了最近学到的利用requests和bs4第三方库共同作用,基本可以应对python获取静态网页数据的相关问题。但是如果现实中的网页往往比想象中复杂的多,网页也早已不再是纯静态网页。

就比如在第一篇文章中爬取的网易云课堂计算机专业大学课程中,如果我们进一步爬取计算机专业可以就业的岗位信息时,通过开发者工具,我们发现,我们所需要的数据位于id="j-smartSpec" 的div中,

然而,我们利用之前的方法进行会发现最后得到的list为空,那么我们检查一下源代码,好不容易找到了意料之中的标签id,但是我们惊奇的发现,里面什么都没有呀:

好气呀!~可是对于渴望获取想要的数据的决心,我们当然要有一探究竟的耐心的啦~经过多种方式,我们肯定会了解到这是AJAX在捣鬼,AJAX 是一种用于创建快速动态网页的技术。 这种技术使我们可以通过在后台与服务器进行少量数据交换,从而使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,浏览器可以对网页的某部分进行更新。

此时想要获取数据,就要考虑它是通过什么传递新的信息给我们。

实际就是python对动态网页、异步加载的爬取。

————————————————————————————————真^分界线

以上引出本文的主题。

正文

一、方法分析

其实任何动态产生的内容,要么是本地计算,要么是从服务器获取的。前者看js,后者需要抓包。而后者经常配上各种参数加密,不过既然浏览器能正确发送参数,那么就证明肯定有办法模拟(当然不容易)。如果有能力,模拟发包。如果嫌麻烦,用现成的包来模拟操作浏览器。

那么通常来讲,获取动态数据有两种思路或者说是方法:

1. 分析页面请求 2. 利用selenium模拟浏览器行为或其他抓包工具直接获取(比较暴力有没有)

效率最高的就是分析出请求数据的URL 一般都可以 而selenium 实在没辙的时候再用。

本篇文章也仅对第一种方法进行介绍(当然是要实货,不动手是没有用滴),若之后几天仍然很闲,会继续介绍下一种方法

二、开始战斗(目标:股票|上海证券交易所

说了半天,总算要开始了。一年之计在于春,一天之计在于晨。

我们起码要先确定一个方向,看了一下目标页面:

有用的就是公司代码,公司简称,A股代码,A股简称以及A股总资本和A股流通资本这几项。

所以我们的目标就是爬它30页,这些信息全部都要。

三、寻找数据位置

还是以前的基本思路,首先在页面找准数据位置检查,找到标签所在位置,在前言中我们大概也有了些许经验,这时我们试探地打开源代码,这次看到什么都没有似乎也不那么生气了~

接下来是没有介绍过的东西!!即分析出AJAX加载出的文件是哪一个:

如图,在开发者工具Network中的JS中分析,如果感觉实在太多文件不好分析,那么我们发现上面有上市A股点击会小范围刷新的现象,最终可以完全明确目标

这样一来,我们可以说是完成了一半了(其他如果轻车熟路就基本没有什么了)

下一步就是打开目标验证一下有没有我们需要的数据

What????这又是啥情况

嘿嘿,这真的心里又是一惊,403码表示什么呢,就是我们没有权限浏览目标地址。这是网站的自我保护行为。

那咋办呢?我们没有权限啊,可是我们在自己原来的页面不是可以获取这些的嘛!

所以,这里就用到了让我们的虫去模拟人的操作。在前篇一笔带过,其实就是通过修改Request-Headers中Cookie,User-Agent,Referer等信息来使我们的访问请求就像是真人访问一般。而需要修改的内容可以在Headers中查看:

则可保存如下:

headers={'Cookie':'yfx_c_g_u_id_10000042=_ck18012900250116338392357618947; VISITED_MENU=%5B%228528%22%5D; yfx_f_l_v_t_10000042=f_t_1517156701630__r_t_1517314287296__v_t_1517320502571__r_c_2',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36',
'Referer':'http://www.sse.com.cn/assortment/stock/list/share/'
}

通常包含这三个元素即足以证明是‘人’。这样我们已经可以找的到数据了。

四、处理分析数据(将数据JSON格式化并解析JSON)

好了,数据找到了,并且我们可以在开发者工具preview中看到,数据储存为JSON格式(JSON格式的数据本质上是一种被格式化了的字符串,遵循一定的语法规则),现在我们先按照原来的方法先利用requests先获取到数据:

import requests
url='http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback99887&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=1&pageHelp.pageSize=25&pageHelp.pageNo=1&_=1517320503161'
response=requests.get(url,headers=headers) #注意,这一步即将我们‘人’的信息传入请求中

那么,下一步就要获取目标中的JSON数据,此时我们将开发者工具中Response复制后,粘贴到json在线解析及格式化验证验证是否是格式化的标准JSON数据。
检验后发现结果出错

那么我们就需要分析哪里语法有问题,此处不过多赘述,直接贴出删除和添加的部分:

删除部分:开头的以及结尾的

添加部分:添加至开头,并在结尾添加‘}’即可看到解析出的JSON结构:

好了,到这里数据JSON格式化也基本完成。而在解析时,我们需要用到python自带的json库以及jsonpath第三方库(若是windows系统直接在cmd输入pip install jsonpath 即可安装):

import json
from jsonpath import jsonpath #从jsonpath库中导入jsonpath方法
json_str='{"content":'+response.text[19:-1]+'}' #即将我们刚才分析出的结果进行格式化
unicodestr=json.loads(json_str) #json的loads()方法用于将json的字符串转换成python默认的unicode字符串,还有一个dumps()方法是将python对象转换成json字符串,其中的转换之间的关系不再赘述,有兴趣自行查阅相关资料

接下来就是通过jsonpath寻找我们需要的数据(类似于之前的soup.select()寻找的思想,但是这里是基于jsonpath的查询)

通过分析两个,我们可以轻易地发现其规律性,而jsonpath的使用可以参照jsonpath的简单入门,或者自行查阅官方文档。

由于A股中A股名称代码与公司名称代码均一致,故:

    COMPANY_CODE=jsonpath(a,'$..pageHelp..COMPANY_CODE')#公司/A股代码
    COMPANY_ABBR=jsonpath(a,'$..pageHelp..COMPANY_ABBR')#公司/A股简称
    totalShares=jsonpath(a,"$..pageHelp..totalShares") #A股总资本
    totalFlowShares=jsonpath(a,'$..pageHelp..totalFlowShares') #A股流动资本

至此,解析数据也完成了。

五、整理打印数据

print('公司/A股代码','\t','公司/A股简称','\t','A股总资本','\t','A股流动资本')
    L1=list()
    L2=list()
    L3=list()
    L4=list()
    for x in COMPANY_CODE:
        L1.append(x)
    for x in COMPANY_ABBR:
        L2.append(x)
    for x in totalShares:
        L3.append(x)
    for x in totalFlowShares:
        L4.append(x)
#由于同时解四个包太过复杂,python不干,故拆分开来
    x=0
    while(x<len(L1)):
        print(L1[x],'\t','\t',L2[x],'\t','\t',L3[x],'\t','\t',L4[x])
        x+=1


这样我们就爬下一页了:经验证无误。

六、扩大战果(儿时吹的牛皮还是要补的)

前面夸下海口要抓30页,怎么就能没有了呢?其实后面已经基本没有什么了,有兴趣的朋友可以和我一起补补课。

感觉内容有些多,我在这里简单描述思路,就是我们要分析第一页第二页第三页等之间的目标数据地址的url的相似之处,或者说其中的规律,比如:

第二页:http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback46762&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=2&pageHelp.pageSize=25&pageHelp.pageNo=2&pageHelp.endPage=21&_=1517320503162

第三页:http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback61233&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=3&pageHelp.pageSize=25&pageHelp.pageNo=3&pageHelp.endPage=31&_=1517320503163

很轻松就可以对比出不同和相似之处,可以说仅仅在个别关键字部分进行了修改。

故提取三十页的代码,以及之前的各种步骤,我们可以封装到函数以便调取使用:

def find_pageA(c): #根据传递参数c(提取的页数)来选择目标url地址
        return 'http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback13897&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage='+str(c)+'&pageHelp.pageSize=25&pageHelp.pageNo='+str(c)+'&pageHelp.endPage='+str(c)+'1&_=151731428806'+str(c)
def datascreenA(a):#封装解析输出的部分
    COMPANY_CODE=jsonpath(a,'$..pageHelp..COMPANY_CODE')
    COMPANY_ABBR=jsonpath(a,'$..pageHelp..COMPANY_ABBR')
    totalShares=jsonpath(a,"$..pageHelp..totalShares")
    totalFlowShares=jsonpath(a,'$..pageHelp..totalFlowShares')
    print('公司/A股代码','\t','公司/A股简称','\t','A股总资本','\t','A股流动资本')
    L1=list()
    L2=list()
    L3=list()
    L4=list()
    for x in COMPANY_CODE:
        L1.append(x)
    for x in COMPANY_ABBR:
        L2.append(x)
    for x in totalShares:
        L3.append(x)
    for x in totalFlowShares:
        L4.append(x)
    x=0
    while(x<len(L1)):
        print(L1[x],'\t','\t',L2[x],'\t','\t',L3[x],'\t','\t',L4[x])
        x+=1
def collect_30_pagesA():#调取30页,相当于主函数
    c=1
    while(c<31):
        time.sleep(2)
        print('第', c, '页:')
        response=requests.get(find_pageA(c),headers=headers)
        a='{"content":'+response.text[19:-1]+'}'
        b=json.loads(a)
        datascreenA(b)
        c+=1

终结

不知不觉写了这么多,真的是闲的太慌了。其实除了A股还有B股,有兴趣也可以继续爬下去,虽然我不知道有什么价值目前……另外就是前言部分的爬取也可以尝试一下,可能会发现那个文件中的数据又是从其他地方获取的……恕我能力有限,原理不是特别清晰,故而没有深入讲解那个,望各位指教。当然暴力破解是可行的,但是……又不着急干啥能不用就不用呗,^_^。

主要还是多动手多实战吧,光看是没有用的,之后有用到需要保存的东西,可能还需要接触一些关联文件的库以及数据库等等,包括如何通过图片链接下载图片……

总之,有兴趣又闲的朋友可以交流,不足之处望及时指出共同进步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【2】Python爬虫:分析AJAX传递的JSON获取数据-初步分析动态网页(1) 的相关文章

  • 从 asyncio 子进程获取实时输出

    我正在尝试使用 Python asyncio 子进程来启动交互式 SSH 会话并自动输入密码 实际用例并不重要 但它有助于说明我的问题 这是我的代码 proc await asyncio create subprocess exec ssh
  • setColumnStretch 和 setRowStretch 如何工作

    我有一个使用构建的应用程序PySide2它使用setColumnStretch用于柱拉伸和setRowStretch用于行拉伸 它工作得很好 但我无法理解它是如何工作的 我参考了 qt 文档 但它对我没有帮助 我被困在括号内的两个值上 例如
  • 使用 pyppeteer 与 asyncio 关联来抓取内容

    我用 python 结合编写了一个脚本pyppeteer随着asyncio从其登陆页面抓取不同帖子的链接 并最终通过跟踪通向其内页的 url 来获取每个帖子的标题 我这里解析的内容不是动态的 但是 我利用了pyppeteer and asy
  • 嵌套函数中的变量作用域

    有人可以解释为什么以下程序失败 def g f for in range 10 f def main x 10 def f print x x x 1 g f if name main main 带有消息 Traceback most re
  • 如何使用 tkinter 使用网格功能显示不同的图像?

    我想使用显示文件夹中的图像grid 但是当我尝试使用以下代码时 我得到了迭代单个图像的输出 My code def messageWindow win Toplevel path C Users HP Desktop dataset for
  • 使用python编辑html,但是lxml将漂亮的html实体转换为奇怪的编码

    我正在尝试使用 python 带有 pyquery 和 lxml 来更改和清理一些 html Eg html div p It 146 s a spicy meatball p div lxml html clean 函数 clean ht
  • MacOS Big Sur 中的 NPM 错误“找不到 Python 可执行文件”

    我已经花了整整一周的时间寻找这个问题的答案 但没有成功 我查看了每个 StackOverflow 帖子 Google 的每一篇文章以及我能找到的每个相关的 Github 问题 大多数相关错误似乎都比较旧 所以我想知道我的问题是否由于我使用的
  • TemplateSyntaxError:“settings_tags”不是有效的标签库

    当我尝试运行此测试用例时 出现此错误 这是在我的 django 应用程序的tests py 中编写的 def test accounts register self self url http royalflag com pk accoun
  • 如何使用 Pycharm 运行 fast-api 服务器?

    我有一个简单的 API 函数 如下所示 from fastapi import FastAPI app FastAPI app get async def read root return Hello World 我正在使用启动服务器uvi
  • 在Python中,如何通过去掉括号和大括号来打印Json

    我想以一种很好的方式打印 Json 我想去掉方括号 引号和大括号 只使用缩进和行尾来显示 json 的结构 例如 如果我有一个像这样的 Json A A1 1 A2 2 B B1 B11 B111 1 B112 2 B12 B121 1
  • 如何停止 PythonShell

    如何终止 停止 Node js 中 PythonShell 执行的 Python 脚本的执行 我在交互模式下运行 输出通过 socket io 发送到给定的房间 如果没有更多的客户端连接到这个房间 我想停止 python 脚本的执行 这是我
  • python 硒 按名称查找元素

    查找电子邮件输入的正确代码是什么https accounts google com ServiceLogin html 是
  • 使用最新值进行采样

    考虑以下系列 created at 2014 01 27 21 50 05 040961 80000 00 2014 03 12 18 46 45 517968 79900 00 2014 09 05 20 54 17 991260 636
  • 在基本 Tensorflow 2.0 中运行简单回归

    我正在学习 Tensorflow 2 0 我认为在 Tensorflow 中实现最基本的简单线性回归是一个好主意 不幸的是 我遇到了几个问题 我想知道这里是否有人可以提供帮助 考虑以下设置 import tensorflow as tf 2
  • 数据类和属性装饰器

    我一直在阅读 Python 3 7 的数据类 作为命名元组的替代品 我通常在必须将数据分组到结构中时使用它 我想知道数据类是否与属性装饰器兼容 以便为数据类的数据元素定义 getter 和 setter 函数 如果是这样 是否在某处进行了描
  • 如何在 Jupyter Notebook 中选择 conda 环境

    我安装了 Anaconda 5 3 和 Python 3 7 根环境 之后我使用 Python 3 6 创建了一个新环境 py36 我激活了新环境activate py36 conda env list表明环境是活跃的 但是当我启动 Jup
  • 从函数在 python 3 中创建全局变量

    我想知道为什么在函数结束后我无法访问变量 variable for raw data 代码是这样的 def htmlfrom Website URL import urllib request response urllib request
  • model.predict() 返回类而不是概率

    Hello 我是第一次使用 Keras 我训练并保存了一个模型 作为 json 文件及其权重 该模型旨在将图像分为 3 个类别 我的编译方法 model compile loss categorical crossentropy optim
  • 基于 Web 请求在 Airflow 上运行作业

    我想知道是否可以在通过 HTTP 收到请求时执行气流任务 我对 Airflow 的调度部分不感兴趣 我只是想用它来代替芹菜 因此 示例操作如下所示 用户提交一份表格 请求某些报告 后端接收请求并向用户发送请求已收到的通知 然后后端使用 Ai
  • 如何从 Pandas 数据框函数调用中回顾之前的行?

    我正在研究 回测交易系统 我有一个包含 OHLC 数据的 Pandas 数据框 并添加了几个计算列 https stackoverflow com questions 12376863 adding calculated columns t

随机推荐

  • Vue3-初识Vue3、创建Vue3工程、vue3组合式API(setup、ref函数、reactive函数)、响应式原理、计算属性、监视属性

    Vue3 1 目录 Vue3 1 一 Vue3简介 二 创建Vue3 0工程 1 使用vue cli创建 2 使用vite创建 三 常用的Composition API 组合式API 1 拉开序幕的setup 2 ref函数 3 react
  • Flutter沉浸式透明状态栏-flutter自定义凸起BottomAppBar导航

    注意 flutter项目默认是使用Kotlin语言 在Google I O 2017中 Google 宣布 Kotlin 取代 Java 成为 Android 官方开发语言 Kotlin详情见 https www kotlincn net
  • 异常处理--java.lang.reflect.MalformedParameterizedTypeException

    异常信息 org springframework beans factory BeanCreationException Error creating bean with name sqlSessionFactory defined in
  • C语言指针详解

    1 指针是什么 指针是内存中一个最小单元的编号 也就是地址 平时口语中说的指针 通常指的是指针变量 是用来存放内存地址的变量 所以 指针就是地址 口语中说的指针通常指的是指针变量 1 指针变量 我们可以通过 取地址操作符 取出变量的内存其实
  • 活动效果评估体系,该怎么搭建?

    如果让你来评估这次活动 你会怎么分析 无论是面试还是工作 做数据分写的同学都经常遇到这个问题 今天我们系统讲解一下 场景还原 某音乐类APP 对新用户进行一个新注册即送7天会员权益的活动 用户注册后 自主决定是否点击领取 为期1个月 问 如
  • python函数定义参数类型和返回值类型

    python中我们也可以定义函数的参数类型和返回值类型 如下代码 函数参数和返回值的类型声明 python函数类型的声明 更加有意义 更加实用一些 def add a b param a int param b int return int
  • C++ STL中map.erase(it++)用法原理解析

    之前在代码中使用map erase函数时 误搬了vector erase的用法 导致Server down掉了 好在在测试环境就及时发现了问题 在上线前进行了补救 以下总结一下map erase的正确用法 首先看一下在循环中使用vector
  • 灰灰-325-326-327-2019中南大学计算机上机-走台阶(3)

    1 n个台阶 一次走1阶或2阶 问走n阶有多少可能 1 lt n lt 1000 000 结果用1000 0000 7取模输出 输入格式 输入台阶数n 输出格式 结果用1000 0000 7取模输出 输入样例 3 输出样例 3 includ
  • 【技巧】各编辑器基础开发快捷键

    文章目录 一 IDEA 二 vim 1 各个模式的相互切换 2 正常模式 3 插入模式 4 底行模式 5 视图模式 三 Visual Studio 2017 四 PyCharm 一 IDEA psvm 回车 快速打出main函数 sout
  • docker网络自定义

    docker网络自定义 书接上回 我们认识了docker0网络以及 link参数的使用 https blog csdn net hello list article details 124815842 今天来了解下docker自定义网络 那
  • Java描述贪心算法解决背包问题

    思路 首先将物品根据性价比排好序在一个集合里 性价比 价格 重量 然后根据性价比从大到小依次依次放入背包 如果没办法放入这个物品的全部 就放入一部分 如果可以放入全量物品 就放入全量物品 Main java的代码 import java u
  • get和post区别

    get参数通过url传递 post放在post是放在请求头的包体 request body 中 因为参数直接暴露在url中 get比post更不安全 所以不能用来传递敏感信息 get请求在url中传递的参数是有长度限制的 get提交的数据最
  • 『动态规划·差分』队列

    P r o b l e m mathrm Problem Problem S o l u t i o n mathrm Solution Solution 首先考虑第一小问 问题转化为 每一行的问题互相独立 令 c j a i j a 1
  • Java之经典排序算法(一)

    一 冒泡排序 不稳定的排序算法 快希选堆 1 算法思路 比较相邻元素 如果第一个比第二个大 则交换这两个元素 从第一个元素开始依次往后比较相邻两个元素 直到最后一个比较完 这样最后一个元素就是最大的元素 再次从第一个元素开始依次往后比较相邻
  • 锁,避免虚假唤醒,注意死锁

    unique lock
  • 记录kitti数据集的坐标系转换问题

    Calib文件说明 以00000 txt文件为例 详细介绍每行含义 P0 7 070493000000e 02 0 000000000000e 00 6 040814000000e 02 0 000000000000e 00 0 00000
  • DC-DC电源模块输出先放大电容还是小电容

    最好的资料是电容厂家的设计指南 1 电容简单的等效模型是C ESL ESR 2 通常电解电容容量越大 ESR越小 ESL越大 承受纹波电流越大 3 电流流经阻抗最小路径 4 大电流 PCB走线电阻不能忽略 高频纹波电流PCB走线电感不能忽略
  • C语言之结构体内存的计算

    结构体的内存 一 提出疑问 结构体占用的是一片连续的内存空间 大小是由成员变量的类型决定的 但并不是计算所有成员变量的类型大小之和那么简单 先举一个实例 struct student int age 4个字节 int telephone 4
  • win系统使用frp端口映射实现内网穿透,配置“任务计划程序”提高稳定性

    Github下载最新版frp https github com fatedier frp releases download v0 48 0 frp 0 48 0 windows amd64 zip 解压把frpc exe和frpc ini
  • 【2】Python爬虫:分析AJAX传递的JSON获取数据-初步分析动态网页(1)

    前言 这是本人写的第二篇文章 希望能够帮助到一些和我一样的python爬虫初学者 在第一篇文章中 我总结了最近学到的利用requests和bs4第三方库共同作用 基本可以应对python获取静态网页数据的相关问题 但是如果现实中的网页往往比