Ajax数据爬取

有时我们用requests 抓取页面得到的结果,可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,而使用requests 得到的结果中并没有这些数据。这是因为 requests 获取的都是原始 HTML 文档,而浏览器中的页面是JavaScript 处理数据后生成的结果,这些数据有多种来源:可能是通过 Ajax 加载的,可能是包含在 HTML文档中的,也可能是经过 JavaScript 和特定算法计算后生成的。

对于第一种来源,数据加载是一种异步加载方式,原始页面最初不会包含某些数据,当原始页面加载完后,会再向服务器请求某个接口获取数据,然后数据才会经过处理从而呈现在网页上,这其实是发送了一个 Ajax 请求。

按照 Web 的发展趋势来看,这种形式的页面越来越多。甚至网页的原始 HTML 文档不会包含任何数据,数据都是通过 Ajax 统一加载后呈现出来的,这样使得 Web 开发可以做到前后端分离,减小服务器直接渲染页面带来的压力。

所以如果遇到这样的页面,直接利用requests等库来抓取原始 HTML文档,是无法获取有效数据的,这时需要分析网页后台向接口发送的 Aiax 请求。如果可以用 requests 模拟 Aiax 请求,就可以成功抓取页面数据了。

所以,本章我们的主要目的是了解什么是 Ajax,以及如何分析和抓取 Ajax 请求。

什么是Ajax

Ajax,全称为 Asynchronous JavaScript and XML,即异步的 JavaScript 和 XML。它不是一门编程语言,而是利用 JavaScript 在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页内容的技术。

对于传统的网页,如果想更新其内容,就必须刷新整个页面,但有了Aiax,可以在页面不被全部刷新的情况下更新。这个过程实际上是页面在后台与服务器进行了数据交互,获取数据之后,再利用JavaScript 改变网页,这样网页内容就会更新了。

可以到 W3School上体验几个实例感受一下:https://www.w3school.com.cn/js/js_ajax_http_send.asp

  1. 实例引入

浏览网页的时候,我们会发现很多网页都有“下滑查看更多”的选项。拿微博来说,可以登录https://m.weibo.cn/为例,一直下滑,可以发现下滑几条微博之后,再向下就没有了,转而会出现一个加载的动画,不一会儿下方就继续出现了新的微博内容,这个过程其实就是 Ajax 加载的过程,如下图所示。

在这里插入图片描述
能够看出,页面其实并没有整个刷新这意味着页面的链接没有变化,但是网页中却多了新内容,也就是后面刷出来的新微博。这就是通过 Ajax 获取新数据并呈现的过程。

  1. 基本原理

初步了解了 Ajax之后,我们接下来详细了解它的基本原理。从发送 Aiax 请求到网页更新的这个过程可以简单分为以下3步–发送请求、解析内容、渲染网页。下面分别详细介绍一下这几个过程。

  • 发送请求

我们知道JavaScript可以实现页面的各种交互功能,Ajax也不例外,它也是由JavaScript实现的,实现代码如下:

var xmlhttp;if(window.XMLHttpRequest){xmlhttp=new XMLHttpRequest();
}else{//code for IE6、 IE5xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange-function(){if(xmlhttp.readyState==4&&xmlhttp.status==200{document.getElementById("myDiv").innerHTML=xmlhttp.responseText;}
}
xmlhttp.open("POST","/ajax/",true);
xmlhttp.send();

这是 JavaScript 对 Ajax 最底层的实现,实际上就是先新建一个 XMLHttpRequest 对象 xmlhttp,然后调用 onreadvstatechange属性设置监听,最后调用 open和 send方法向某个链接(也就是服务器)发送请求。前面用 Python 实现请求发送之后,可以得到响应结果,但这里的请求发送由 JavaScript 完成。由于设置了监听,所以当服务器返回响应时,onreadystatechange 对应的方法便会被触发,然后在这个方法里面解析响应内容即可。

  • 解析内容

服务器返回响应之后,onreadystatechange 属性对应的方法就被触发了,此时利用 xmlhttp 的responseText属性便可得到响应内容。这类似于Python 中利用requests 向服务器发起请求,然后得到响应的过程。返回内容可能是 HTML,可能是 JSON,接下来只需要在方法中用 JavaScript 进一步处理即可。如果是 JSON 的话,可以进行解析和转化。

  • 渲染网页

JavaScript有改变网页内容的能力,因此解析完响应内容之后,就可以调用JavaScript 来基于解析完的内容对网页进行下一步处理了。例如,通过 document.getElementBvId().innerHTML操作,可以更改某个元素内的源代码,这样网页显示的内容就改变了。这种操作也被称作 DOM 操作,即对网页文档进行操作,如更改、删除等。

上面“发送请求”部分,代码里的 document.getElementById(“myDiv”).innerHTML=xmlhttp.responseText便是将 ID 为 myDiv 的节点内部的 HTML 代码更改为了服务器返回的内容,这样 myDiv 元素内部便会呈现服务器返回的新数据,对应的网页内容看上去就更新了。

我们观察到,网页更新的3个步骤其实都是由 JavaScript 完成的,它完成了整个请求、解析和渲染的过程。

再回想微博的下拉刷新,其实就是 JavaScript 向服务器发送了一个 Ajax 请求,然后获取新的微博数据,对其做解析,并渲染在网页中。

因此我们知道,真实的网页数据其实是一次次向服务器发送 Ajax 请求得到的,要想抓取这些数据,需要知道 Ajax 请求到底是怎么发送的、发往哪里、发了哪些参数。我们知道这些以后,不就可以用 Python 模拟发送操作,并获取返回数据了吗?

Ajax分析方法

这里还以之前的微博为例,我们知道下拉刷新的网页内容由 Aiax 加载而得,而且页面的链接没有发生变化,那么应该到哪里去查看这些Ajax请求呢?

  1. 分析案例
    此处还需要借助浏览器的开发者工具,下面以Chrome浏览器为例来介绍。

首先,用 Chrome 浏览器打开微博链接 https://m.weibo.cn可以登录自己的微博,然后在页面中单击鼠标右键,从弹出的快捷菜单中选择“检查”选项,此时便会弹出开发者工具,如下图所示。

在这里插入图片描述
前面也提到过,这里展示的就是页面加载过程中,浏览器与服务器之间发送请求和接收响应的所有记录。

事实上,Ajax有其特殊的请求类型,叫作xhr。在下图中,我们可以发现一个名称以 getindex 开头的请求,其 Type 就为 xhr,意味着这就是一个 Ajax 请求。用鼠标单击这个请求,可以查看其详细信息。
在这里插入图片描述

从上图的右侧可以观察这个 Ajax 请求的 Request Headers、URL和 Response Headers 等信息。其中 Request Headers 中有一个信息为 X-Requested-With:XMLHttpRequest,这就标记了此请求是 Ajax 请求,如下图所示。
在这里插入图片描述
随后单击一下 Preview,就能看到响应的内容,如下图所示。这些内容是 JSON 格式的,这里Chrome为我们自动做了解析,单击左侧箭头即可展开和收起相应内容。
在这里插入图片描述
JavaScript接收到这些数据之后,再执行相应的渲染方法,整个页面就渲染出来了。

另外,也可以切换到 Response 选项卡,从中观察真实的返回数据,如下图所示:
在这里插入图片描述
接下来,切回第一个请求,观察一下它的 Response 是什么,如下图所示。

在这里插入图片描述

这是最原始的链接返回的结果,其代码只有不到 50 行,结构也非常简单,只是执行了一些 JavaScript 语句。

所以说,微博页面呈现给我们的真实数据并不是最原始的页面返回的,而是执行JavaScript 后再次向后台发送 Ajax请求,浏览器拿到服务器返回的数据后进一步渲染得到的。

  1. 过滤请求

利用 Chrome 开发者工具的筛选功能能够筛选出所有 Ajax请求。在请求的上方有一层筛选栏,直接单击 XHR,之后下方显示的所有请求便都是 Ajax 请求了,如下图所示。

在这里插入图片描述
接下来,不断向上滑动微博页面,可以看到页面底部有一条条新的微博被刷出,开发者工具下方也出现了一个个新的 Ajax 请求,这样我们就可以捕获所有的 Ajax 请求了。

随意点开其中一个条目,都可以清楚地看到其Request URL、Request Headers、Response Headers、Response Body 等内容,此时想要模拟 Ajax 请求的发送和数据的提取就非常简单了。

下图展示的内容便是我的某一页微博的列表信息

在这里插入图片描述

到现在为止,我们已经可以得到 Aiax 请求的详细信息了,接下来只需要用程序模拟这些 Ajax 请求,就可以轻松提取我们所需的信息。

Ajax分析与爬虫实战

本节我们会结合一个实际的案例,来看一下 Ajax 分析和爬取页面的具体实现。

  1. 准备工作

开始分析之前,需要做好如下准备工作。

  • 安装好 Python 3(最低为 3.6 版本 ),并成功运行 Python 3 程序。
    -了解 Python HTTP 请求库 requests 的基本用法。
  • 了解 Ajax 基础知识和分析 Ajax 的基本方法。

以上内容在前面的博客中均有讲解,如尚未准备好,建议先熟悉一下这些内容。

  1. 爬取目标

本节我们以一个示例网站来试验一下 Ajax的爬取,其链接为:https://spa1.scrape.center/,该示例网站的数据请求是通过 Ajax完成的,页面的内容是通过JavaScript 渲染出来的,页面如下图所示。
在这里插入图片描述

此时我们需要爬取的数据,包括电影的名称、封面、类别、上映日期、评分剧情简介等信息。
本节我们需要完成的目标如下

  • 分析页面数据的加载逻辑。
  • 用 requests 实现 Ajax 数据的爬取。
  • 将每部电影的数据分别保存到 MongoDB 数据库。
    由于本节主要讲解 Ajax,所以数据存储和加速部分就不再展开详细实现了,主要是讲解 Ajax 分析和爬取的实现。
    好,现在就开始吧。
  1. 初步探索

我们先尝试用之前的 requests 直接提取页面,看看会得到怎样的结果。用最简单的代码实现一下requests 获取网站首页源码的过程,代码如下:

import requestsurl = 'https://spa1.scrape.center/'
html = requests.get(url).text
print(html)

运行结果如下:

<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible 
content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1">
<link rel=icon href=/favicon.ico><title>Scrape | Movie</title><link href=/css/chunk-
700f70e1.1126d090.css rel=prefetch><link href=/css/chunk-d1db5eda.0ff76b36.cssrel=prefetch><link href=/js/chunk-700f70e1.0548e2b4.js rel=prefetch><linkhref=/js/chunk-d1db5eda.b564504d.js rel=prefetch><link href=/css/app.ea9d802a.cssrel=preload as=style><link href=/js/app.17b3aaa5.js rel=preload as=script><linkhref=/js/chunk-vendors.683ca77c.js rel=preload as=script><linkhref=/css/app.ea9d802a.css rel=stylesheet></head><body><noscript><strong>We'resorry but portal doesn't work properly without JavaScript enabled. Please enableit to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.683ca77c.js></script><script src=/js/app.17b3aaa5.js></script></body></html>

可以看到,爬取结果就只有这么一点HTML内容,而我们在浏览器中打开这个网站,却能看到如下图所示的页面。
在这里插入图片描述
在 HTML中,我们只能看到源码引用的一些JavaScript和CSS 文件,并没有观察到任何电影数据信息。

遇到这样的情况,说明我们看到的整个页面都是JavaScript渲染得到的,浏览器执行了HTML中引用的 JavaScript 文件,JavaScript 通过调用一些数据加载和页面渲染方法,才最终呈现了上图展示的结果。这些电影数据一般是通过 Aiax加载的,JavaScript在后台调用 Aiax数据接口,得到数据之后,再对数据进行解析并渲染呈现出来,得到最终的页面。所以要想爬取这个页面,直接爬取 Ajax 接口,再获取数据就好了

上面我们已经了解了 Ajax 分析的基本方法,下面一起分析一下 Ajax 接口的逻辑并实现数据爬取吧。

  1. 爬取列表页

首先分析列表页的 Ajax 接口逻辑,打开浏览器开发者工具,切换到Network面板,勾选 PreserveLog 并切换到 XHR 选项卡,如下图所示。
在这里插入图片描述

接着重新刷新页面,再单击第2页、第3页、第4页的按钮,这时可以观察到不仅页面上的数据发生了变化,开发者工具下方也监听到了几个 Ajax 请求,如下图所示。
在这里插入图片描述

我们切换了4页,每次翻页也出现了对应的 Aiax 请求。可以点击査看其请求详情,观察请求 URL、参数和响应内容是怎样的,如下图所示。

在这里插入图片描述
这里我点开了最后一个结果,观察到其Ajax接口的请求 URL为 https://spa1.scrape.center/api/movie?limit=10&ofset=40,这里有两个参数:一个是limit,这里是10;一个是 offset,这里是 40。

观察多个 Ajax 接口的参数,我们可以总结出这么一个规律:limit 一直为10,正好对应每页 10条数据;offset 在依次变大,页数每加1,offset 就加10,因此其代表页面的数据偏移量。例如第2页的 offset 为 10 就代表跳过 10 条数据,返回从 11 条数据开始的内容,再加上 limit 的限制,最终页面呈现的就是第 11条至第 20 条数据。

接着我们再观察一下响应内容,切换到Preview 选项卡,结果如下图所示。

在这里插入图片描述
可以看到,结果就是一些 JSON 数据,其中有一个 results 字段,是一个列表,列表中每一个元素都是一个字典。观察一下字典的内容,里面正好可以看到对应电影数据的字段,如 name、alias、cover、categories。对比一下浏览器页面中的真实数据,会发现各项内容完全一致,而且这些数据已经非常结构化了,完全就是我们想要爬取的数据,真的是得来全不费工夫。

这样的话,我们只需要构造出所有页面的 Ajax接口,就可以轻松获取所有列表页的数据了先定义一些准备工作,导人一些所需的库并定义一些配置,代码如下:

import requests
import logginglogging.basicConfig(level=logging.INFO, format='%(asctime)s-%(levelname)s:%(message)s')
INDEX_URl = 'https://spa1.scrape.center/api/movie/?limit={limit}&offset-{offset}'

这里我们引人了 requests 和 logging 库,并定义了 logging 的基本配置。接着定义了 INDEX URL,这里把 limit 和 offset 预留出来变成占位符,可以动态传人参数构造一个完整的列表页 URL。

下面我们实现一下详情页的爬取。还是和原来一样,我们先定义一个通用的爬取方法,其代码如下:

def scrape_api(url):logging.info('scraping %s...', url)try:response = requests.get(url)if response.status_code == 200:return response.json()logging.error('get invalid status code %s while scraping %s', response.status_code, url)except requests.RequestException:logging.error('error occurred while scraping %s', url, exc_info=True)

这里我们定义了一个 scrape api方法,和之前不同的是,这个方法专门用来处理 JSON接口。最后的 response 调用的是 json 方法,它可以解析响应内容并将其转化成 JSON 字符串。

接着在这个基础之上,定义一个爬取列表页的方法,其代码如下:

def scrape_index(page):url = INDEX_URL.format(limit=LIMIT, offset=LIMIT * (page - 1))return scrape_api(url)

这里我们定义了一个 scrape index方法,它接收一个参数 page,该参数代表列表页的页码。scrape_index方法中,先构造了一个url,通过字符串的 format方法,传入 limit 和 offset 的值。这里 limit 就直接使用了全局变量 LIMIT 的值;offset 则是动态计算的,计算方法是页码数减一再乘以 limit,例如第1页的 offset 就是0,第2页的 offset 就是 10,以此类推。构造好 url后,直接调用 scrape_api 方法并返回结果即可。

这样我们就完成了列表页的爬取,每次发送 Ajax请求都会得到 10部电影的数据信息。

由于这时爬取到的数据已经是 JSON 类型了,所以无须像之前那样去解析 HTML 代码来提取数爬到的数据已经是我们想要的结构化数据,因此解析这一步可以直接省略啦。

到此为止,我们能成功爬取列表页并提取电影列表信息了。

  1. 爬取详情页

虽然我们已经可以拿到每一页的电影数据,但是这些数据实际上还缺少一些我们想要的信息,如剧情简介等信息,所以需要进一步进入详情页来获取这些内容。

单击任意一部电影,如《教父》,进入其详情页,可以发现此时的页面 URL已经变成了 https://spa1scrape.center/detail/40,页面也成功展示了《教父》详情页的信息,如下图所示。
在这里插入图片描述
另外,我们也可以观察到开发者工具中又出现了一个 Ajax请求,其 URL为 https://spa1.scrape.
center/api/movie/40/,通过 Preview 选项卡也能看到 Ajax 请求对应的响应信息,如下图所示。
在这里插入图片描述
稍加观察就可以发现,Ajax 请求的 URL后面有一个参数是可变的,这个参数是电影的id,这里是 40,对应《教父》这部电影。

如果我们想要获取 id为 50的电影,只需要把 URL最后的参数改成 50 即可,即 https://spa1.scrape.
center/api/movie/50/,请求这个新的 URL便能获取 id 为 50 的电影对应的数据了。

同样,响应结果也是结构化的JSON 数据,其字段也非常规整,我们直接爬取即可。

现在,详情页的数据提取逻辑分析完了,怎么和列表页关联起来呢?电影 id从哪里来呢?我们回过头看看列表页的接口返回数据,如下图所示。

在这里插入图片描述
可以看到,列表页原本的返回数据中就带有id这个字段,所以只需要拿列表页结果中的 id 来构造详情页的 Aiax 请求的 URL 就好了。

接着,我们就先定义一个详情页的爬取逻辑,代码如下:

DETAIL_URL = 'https://spa1.scrape.center/api/movie/{id}'def scrape_detail(id):url = DETAIL_URL.format(id=id)return scrape_api(url)

这里定义了一个 scrape_detail方法,它接收一个参数 id。这里的实现也非常简单,先根据定义好的 DETAIL_URL 加 id 构造一个真实的详情页 Ajax 请求的 URL,再直接调用 scrape_api 方法传人这个 url即可。

最后,我们定义一个总的调用方法,对以上方法串联调用,代码如下:

def main():for page in range(1, TOTAL_PAGE + 1):index_data = scrape_index(page)for item in index_data.get('results'):id = item.get('id')detail_data = scrape_detail(id)logging.info('detail data %s', detail_data)if __name__ == '__main__':main()

我们定义了一个 main 方法,该方法首先遍历获取页码 page,然后把 page 当作参数传递给scrape_index方法,得到列表页的数据。接着遍历每个列表页的每个结果,获取每部电影的 id。之后把 id 当作参数传递给 scrape_detail方法来爬取每部电影的详情数据,并将此数据赋值为detail_data,最后输出 detail_data 即可。

运行结果如下:
在这里插入图片描述
由于内容较多,这里省略了部分内容。

可以看到,整个爬取工作已经完成了,这里会依次爬取每一个列表页的 Ajax 接口,然后依次爬取每部电影的详情页 Ajax 接口,并打印出每部电影的 Ajax 接口响应数据,而且都是 JSON 格式。至此,所有电影的详情数据,我们都爬取到啦。

全部代码

import requests
import logginglogging.basicConfig(level=logging.INFO, format='%(asctime)s-%(levelname)s:%(message)s')
INDEX_URL = 'https://spa1.scrape.center/api/movie/?limit={limit}&offset-{offset}'def scrape_api(url):logging.info('scraping %s...', url)try:response = requests.get(url)if response.status_code == 200:return response.json()logging.error('get invalid status code %s while scraping %s', response.status_code, url)except requests.RequestException:logging.error('error occurred while scraping %s', url, exc_info=True)LIMIT = 10def scrape_index(page):url = INDEX_URL.format(limit=LIMIT, offset=LIMIT * (page - 1))return scrape_api(url)DETAIL_URL = 'https://spa1.scrape.center/api/movie/{id}'def scrape_detail(id):url = DETAIL_URL.format(id=id)return scrape_api(url)TOTAL_PAGE = 10def main():for page in range(1, TOTAL_PAGE + 1):index_data = scrape_index(page)for item in index_data.get('results'):id = item.get('id')detail_data = scrape_detail(id)logging.info('detail data %s', detail_data)if __name__ == '__main__':main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/891194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud整合skywalking实现链路追踪和日志采集

1.部署skywalking https://blog.csdn.net/qq_40942490/article/details/144701194 2.添加依赖 <!-- 日志采集 --><dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId><version&g…

12.30 Redis网络模型基础 IO NIO多路复用

图片引用自黑马程序员redis 网络模型 上图引用自java guide javaguide NIO

【智行安全】基于Synaptics SL1680的AI疲劳驾驶检测方案

随著车载技术的快速进步&#xff0c;驾驶安全越来越受到重视&#xff0c;而疲劳驾驶是造成交通事故的重要原因之一。传统的驾驶监控技术因精度不足或反应迟缓&#xff0c;无法满足实时监测需求。因此&#xff0c;结合人工智能技术的疲劳驾驶检测系统成为行业新方向&#xff0c;…

手机实时提取SIM卡打电话的信令声音-智能拨号器的SIP线路-双卡双待单通方案

手机实时提取SIM卡打电话的信令声音 --智能拨号器的SIP线路-双卡双待单通方案 一、前言 蓝牙电话的技术方案最初是从蓝牙耳机和车机蓝牙的使用领域延伸出来的技术方式。通过蓝牙的HFP协议&#xff0c;把手机通话的声音和通话事件状态提取出来进行复用和处理。但中国大陆现行…

HTML——26.像素单位

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>像素</title></head><body><!--像素&#xff1a;1.指设备屏幕上的一个点&#xff0c;单位px&#xff0c;如led屏上的小灯朱2.当屏幕分辨率固定时&…

LeetCode:513.找二叉树左下角的

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;513.找二叉树左下角的 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的…

如何使用 ChatGPT Prompts 写学术论文?

第 1 部分:学术写作之旅:使用 ChatGPT Prompts 进行学术写作的结构化指南 踏上学术写作过程的结构化旅程,每个 ChatGPT 提示都旨在解决特定方面,确保对您的主题进行全面探索。 制定研究问题: “制定一个关于量子计算的社会影响的研究问题,确保清晰并与您的研究目标保持一…

Mcnemar‘s exact test

与卡方检验的区别 与fisher exact test区别

全面Kafka监控方案:从配置到指标

文章目录 1.1.监控配置1.2.监控工具1.3.性能指标系统相关指标GC相关指标JVM相关指标Topic相关指标Broker相关指标 1.4.性能指标说明1.5.重要指标说明 1.1.监控配置 开启JMX服务端口&#xff1a;kafka基本分为broker、producer、consumer三个子项&#xff0c;每一项的启动都需要…

网络安全威胁2024年中报告

下载地址&#xff1a; 网络安全威胁2024年中报告-奇安信

AI辅助编码提高病案首页主要诊断编码正确率数据优化方法(2025增量优化版附python源代码)

一、引言 1.1 研究背景与意义 在医疗信息化进程中,病案首页作为病历信息的核心浓缩,承载着疾病分类、医疗统计、医保结算等关键任务,其主要诊断编码的准确性至关重要。准确的编码不仅是医疗质量评估、科研数据分析的基石,更是合理分配医疗资源、保障医保精准支付的关键依…

雷电模拟器安装LSPosed

雷电模拟器最新版支持LSPosed。记录一下安装过程 首先到官网下载并安装最新版&#xff0c;我安装的时候最新版是9.1.34.0&#xff0c;64位 然后开启root和系统文件读写 然后下载magisk-delta-6并安装 ,这个是吾爱破解论坛提供的&#xff0c;号称适配安卓7以上所有机型&#x…

模型 10-10-10旁观思维

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。超脱当下&#xff0c;透视决策长远影响。 1 10-10-10旁观思维的应用 1.1 职业选择决策 背景&#xff1a;小张是一名大学毕业生&#xff0c;面对未来职业的选择感到迷茫。他擅长营销、策略和经济学&a…

ORM框架详解:为什么不直接写SQL?

想象一下&#xff0c;你正在开发一个小型的在线书店应用。你需要存储书籍信息、用户数据和订单记录。作为一个初学者&#xff0c;你可能会想&#xff1a;“我已经学会了SQL&#xff0c;为什么还要使用ORM框架呢&#xff1f;直接写SQL语句不是更简单、更直接吗&#xff1f;” 如…

合合信息亮相CSIG AI可信论坛,全面拆解AI视觉内容安全的“终极防线”

合合信息亮相CSIG AI可信论坛&#xff0c;全面拆解视觉内容安全的“终极防线”&#xff01; &#x1f42f; AI伪造泛滥&#xff0c;我们还能相信“眼见为实”吗&#xff1f; 近期&#xff0c;由中国图象图形学学会主办的CSIG青年科学家会议 AI可信论坛在杭州成功举办。本次论…

Linux实验报告9-进程管理

目录 一&#xff1a;实验目的 二&#xff1a;实验内容 (1)列出当前系统中的所有进程,如何观察进程的优先级? (2)查看当前终端运行的 bash 进程的 PID,在当前终端启动 vim 编辑器并让其在后台执行,然后列出在当前终端中执行的进程的家族树。 (3)请自行挂载U盘或光盘,然后…

17爬虫:关于DrissionPage相关内容的学习01

概述 前面我们已经大致了解了selenium的用法&#xff0c;DerssionPage同selenium一样&#xff0c;也是一个基于Python的网页自动化工具。 DrissionPage既可以实现网页的自动化操作&#xff0c;也能够实现收发数据包&#xff0c;也可以把两者的功能合二为一。 DressionPage的…

【Unity3D】Jobs、Burst并行计算裁剪Texture3D物体

版本&#xff1a;Unity2019.4.0f1 PackageManager下载Burst插件(1.2.3版本) 利用如下代码&#xff0c;生成一个Texture3D资源&#xff0c;它只能脚本生成&#xff0c;是一个32*32*32的立方体&#xff0c;导出路径记得改下&#xff0c;不然报错。 using UnityEditor; using Uni…

最短路径-Dijkstra 算法

前言 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的&#xff0c;因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法&#xff0c;解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展&#xff0c;直到扩展到终点…

ESP32 I2S音频总线学习笔记(一):初识I2S通信与配置基础

文章目录 简介为什么需要I2S&#xff1f;关于音频信号采样率分辨率音频声道 怎样使用I2S传输音频&#xff1f;位时钟BCLK字时钟WS串行数据SD I2S传输模型I2S通信格式I2S格式左对齐格式右对齐格式 i2s基本配置i2s 底层API加载I2S驱动设置I2S使用的引脚I2S读取数据I2S发送数据卸载…