Python爬虫第14节-如何爬取Ajax的数据
目录
前言
一、什么是Ajax
1.1 具体举例
1.2 基本原理
二、Ajax的分析
2.1 查看请求
2.2 过滤请求
三、解析提取Ajax 结果
3.1 分析请求
3.2 分析响应
四、Ajax抓取实战
前言
咱们在使用requests抓取网页的时候,常常会发现,得到的结果和在浏览器中看到的网页不太一样。在浏览器里,页面上的数据都能正常显示,可通过requests获取到的内容里,却没有这些数据。原因就在于,requests获取的只是最原始的HTML文档,而浏览器中呈现出来的页面,是对数据进行JavaScript处理之后才生成的。这些数据来源比较复杂,有的是通过Ajax加载过来的,有的原本就包含在HTML文档里,还有的是通过JavaScript结合特定算法算出来的。
先讲讲第一种来源,也就是通过Ajax加载数据的情况。一开始,原始页面里并不包含某些数据。等原始页面加载完了,它会再向服务器的某个接口发送请求,获取数据,然后这些数据经过处理,才会在网页上显示出来。这个过程,本质上就是发送了一个Ajax请求。
随着Web技术不断发展,现在这种类型的页面越来越常见了。网页的原始HTML文档里根本没有数据,所有的数据都是通过Ajax统一加载之后,才展示到页面上的。这样做,在Web开发中可以实现前后端分离,还能减少服务器直接渲染页面所产生的压力。
所以啊,要是遇到这种页面,直接用requests这类库去抓取原始页面,是没办法获取到有效数据的。这个时候,就得去分析网页在后台向接口发送的Ajax请求。要是能用requests模拟出这个Ajax请求,那我们就可以成功抓取到想要的数据了。
正因为如此,接下来,我们主要来了解一下什么是Ajax,以及如何对Ajax请求进行分析和抓取。
一、什么是Ajax
Ajax,全称为Asynchronous JavaScript and XML(异步JavaScript和XML),是一种用于在网页不刷新的情况下与服务器交换数据并更新部分页面内容的技术。它不是一种编程语言,而是通过使用JavaScript来实现的。
传统网页需要刷新整个页面才能更新内容,而Ajax技术允许只更新页面的一部分,从而提供更流畅的用户体验。这个过程是通过在后台与服务器进行数据交互完成的,获取到的数据再由JavaScript处理以修改页面内容。
要体验Ajax的工作原理,可以访问W3School网站上的几个示例(http://www.w3school.com.cn/ajax/ajax_xmlhttprequest_send.asp)。这些示例展示了如何使用XMLHttpRequest对象向服务器发送请求,包括GET和POST方法的区别,以及如何处理响应数据。通过这些实例,你可以看到如何在不重新加载整个页面的情况下更新网页内容。
总之,Ajax使得Web应用程序能够更加动态和互动,提高了用户的浏览体验。
1.1 具体举例
浏览网页时,我们会发现好多网页都有下滑查看更多的选项。就拿这个微博( https://m.weibo.cn/u/2008333573)来说 。切换到微博页面,一直往下滑,下滑几条微博后,再往下就没了,接着会出现一个加载动画。过一会儿,下方就会继续出现新的微博内容。这个过程,就是Ajax加载的过程。
我们注意到,页面并没有整个刷新,也就是说页面链接没变化,可网页却多了新内容,也就是后面刷出来的新微博。这就是通过Ajax获取新数据并展示出来的过程。
1.2 基本原理
在对Ajax有了一个初步的认识之后,我们进一步深入探究它的基本原理。从发出Ajax请求一直到网页完成更新,整个过程大体上可以划分成三个步骤:
(1)发送请求
(2)解析内容
(3)渲染网页
接下来,我们就对这几个步骤逐一展开,进行详细的讲解。
(1)发送请求
我们都清楚,JavaScript具备实现网页页面上各类交互功能的能力。而Ajax同样也是依靠JavaScript来达成其功能的。实际上,当执行了类似下面这样的代码时:
var xmlhttp;
if (window.XMLHttpRequest) {//code for IE7+, Firefox, Chrome, Opera, Safarixmlhttp=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对象,随后调用它的onreadystatechange属性来设置监听机制。设置好监听后,再调用open()和send()方法,向特定的链接(也就是服务器端)发送请求。就如同我们之前使用Python发送请求能够获取响应结果一样,只不过在这里,请求的发送操作是通过JavaScript来完成的。由于预先设置了监听,一旦服务器返回响应信息,onreadystatechange所对应的方法就会自动被触发执行,届时在这个被触发的方法里对响应内容进行解析处理就可以了。
(2)解析内容
当服务器返回响应后,之前设置的onreadystatechange属性所对应的方法就会被激活。这个时候,借助xmlhttp的responseText属性,就能够获取到服务器返回的响应内容了。
这和我们用Python里的requests库向服务器发送请求并获得响应的过程比较类似。服务器返回的内容形式多样,有可能是HTML格式,也有可能是JSON格式。
获取到响应内容后,接下来只需要在这个被触发的方法里,使用JavaScript对内容做进一步的处理即可。举个例子,如果返回的内容是JSON格式,我们就可以对它进行解析,将其转换成JavaScript能够方便处理的数据结构,比如对象或者数组等。
(3)渲染网页
JavaScript具备对网页内容进行修改的功能。当我们把服务器响应的内容解析完成后,就能够调用JavaScript,依据解析后的内容对网页做进一步的处理。比如说,利用`document.getElementById().innerHTML`这样的操作,就可以实现对网页中某个元素内部源代码的更改,如此一来,网页上显示的内容也就随之发生变化了。这种操作其实就是DOM操作,也就是对Document(网页文档)进行诸如更改、删除之类的操作。
就拿上面提到的例子来讲,`document.getElementById("myDiv").innerHTML=xmlhttp.responseText` 这行代码,将ID为myDiv的节点内部的HTML代码替换成了服务器返回的内容。这样一来,myDiv元素里面就会呈现出服务器新返回的数据,网页的部分内容也就实现了更新。
可以发现,发送请求、解析内容、渲染网页这三个步骤全部是由JavaScript来完成的,它完整地实现了整个Ajax请求、解析以及渲染的流程。
我们再回顾一下微博的下拉刷新功能,本质上就是JavaScript向服务器发送了一个Ajax请求,获取到新的微博数据后,对数据进行解析,然后把数据渲染到网页上展示出来。
由此可知,我们看到的微博页面上那些真实的数据,都是通过一次次的Ajax请求获取到的。要是我们想要抓取这些数据,就必须弄清楚这些请求是如何发送出去的,发送给了哪个服务器,以及发送请求时携带了哪些参数。一旦知道了这些信息,不就可以使用Python来模拟这个请求发送的操作,进而获取到相应的结果了吗?
那么接下来,我们就来探究一下从什么地方能够查看到这些后台的Ajax操作,深入了解它具体是怎样发送的,以及发送请求时具体携带了哪些参数。
二、Ajax的分析
还是以之前说的微博为例。咱们都清楚,微博页面拖动刷新后出现的内容是通过Ajax加载的,并且页面的URL没有改变。那要到哪里才能查看这些Ajax请求呢?
2.1 查看请求
这得靠浏览器的开发者工具,下面我以Chrome浏览器为例详细说说。
先用Chrome浏览器打开微博链接https://m.weibo.cn/u/2008333573 。打开后,在页面上任意位置点击鼠标右键,从弹出来的快捷菜单里找到“检查”选项并点击,这时开发者工具就弹出来了,具体样子参照下图 。
打开开发者工具后,能看到Elements选项卡,这里面展示的是网页的源代码,右侧显示的是节点的样式。
但这些并不是我们要找的内容。我们需要切换到Network选项卡,然后重新刷新页面,这时就能看到选项卡里出现了好多条目,如下图所示。
之前提到过,这里记录的其实就是页面加载的时候,浏览器和服务器之间发送请求以及接收响应的所有情况。
Ajax有专门的请求类型,叫xhr。从下图能看到,有个请求名称是以getIndex开头的,它的Type显示为xhr,这就是一个Ajax请求。用鼠标点击这个请求,就能查看它的详细信息。
在请求详情页面的右侧,可以看到Request Headers、URL和Response Headers等信息。在Request Headers里面,有一项是X-Requested-With:XMLHttpRequest,这就说明这个请求属于Ajax请求,具体可看下图 。
接着,点击一下Preview,就能看到响应内容了,格式是JSON。这里Chrome浏览器自动帮我们解析好了,页面上有箭头,点击箭头就能展开或收起相应内容,具体情况如下图所示。
仔细看能发现,这里返回的是我的个人信息,比如昵称、简介、头像等,这些就是用来渲染个人主页的数据。JavaScript接收到这些数据后,就会执行相应的渲染方法,进而把整个页面渲染出来。
此外,我们还能切换到Response选项卡,在里面能看到服务器真实返回的数据,具体如下图所示。
接下来,回到第一个请求,看看它的Response内容,参考下图。
这是最开始的链接 ( https://m.weibo.cn/u/2008333573 ) 返回的结果,代码不到50行,结构很简单,主要就是执行了一些JavaScript代码。
所以说,我们看到的微博页面的真实数据,不是原始页面直接返回的,而是原始页面执行JavaScript后,又向后台发送Ajax请求,浏览器获取到数据后再进一步渲染出来的 。
2.2 过滤请求
接下来,再用Chrome开发者工具的筛选功能,把所有的Ajax请求筛选出来。在请求的上方有一层筛选栏,直接点击XHR,这时下方显示的所有请求就都是Ajax请求了,如下图所示。
接着,不断滑动页面,可以看到页面底部一条条新微博被刷出来,开发者工具下方也一个个地出现Ajax请求,这样我们就能捕获到所有的Ajax请求了。
随便点开一个条目,都能清楚看到它的Request URL、Request Headers、Response Headers、Response Body等内容。这时,想模拟请求和提取数据就很简单了。下图所示的内容,就是我的某一页微博的列表信息。
到现在,我们已经能分析出Ajax请求的一些详细信息了。接下来,只要用程序模拟这些Ajax请求,就能轻松提取我们需要的信息。
在下一节中,我们用Python实现Ajax请求的模拟,进而实现数据的抓取。
三、解析提取Ajax 结果
还是以微博为例,下面我们要用 Python 来模拟那些 Ajax 请求,把我发布过的微博抓取下来。
3.1 分析请求
先打开 Ajax 的 XHR 过滤器,然后不断滑动微博页面,让新的微博内容加载出来。这时候能看到,会不断有 Ajax 请求发送出去。
从这些请求里选一个,分析它的参数信息。点击这个请求,进入到详情页面。
我们发现,这是一个 GET 类型的请求,请求的链接是(https://m.weibo.cn/api/container/getIndex?type=uid&value=2008333573&containerid=1076032008333573&since_id=3514220849071579),请求带着四个参数,分别是 type、value、containerid、since_id。
再看看其他的请求,会发现它们的 type、value 和 containerid 这三个参数的值一直都不变。type 始终是 uid,value 的值就是页面链接里的数字,其实这个数字就是用户的 id。containerid 呢,是由 107603 加上用户 id 组成的。会变化的参数只有 since_id,很明显,这个参数是用来控制微博分页的,为了防止被爬虫,人家做了另外的处理。
3.2 分析响应
接着,看看刚才选的这个请求的响应内容,如下图所示。
响应内容是 JSON 格式的,浏览器的开发者工具自动帮我们解析好了,方便查看。这里面最关键的两部分信息是 cardlistInfo 和 cards:cardlistInfo 里面有个重要信息叫 total,观察后发现,它表示的是微博的总数量,我们可以根据这个数字来大概估算一下微博有多少页;cards 是一个列表,里面有 10 个元素,展开其中一个元素看看,如下图所示。
mblog内容如下:
{
"visible": {
"type": 0,
"list_id": 0
},
"created_at": "Mon Nov 19 23:30:04 +0800 2012",
"id": "3514220849071579",
"mid": "3514220849071579",
"can_edit": false,
"text": "转发微博",
"source": "360安全浏览器",
"favorited": false,
"pic_ids": [],
"is_paid": false,
"mblog_vip_type": 0,
"user": {
"id": 2008333573,
"screen_name": "林Tangos",
"profile_image_url": "https://tva1.sinaimg.cn/crop.13.13.313.313.180/77b4bd05jw8f44h2k95r8j20990dw0u4.jpg?KID=imgbed,tva&Expires=1744647665&ssig=u%2BVA9Wm0be",
"profile_url": "https://m.weibo.cn/u/2008333573?luicode=10000011&lfid=1076032008333573",
"close_blue_v": false,
"description": "",
"follow_me": false,
"following": false,
"follow_count": 274,
"followers_count": "122",
"cover_image_phone": "https://tva1.sinaimg.cn/crop.0.0.640.640.640/549d0121tw1egm1kjly3jj20hs0hsq4f.jpg",
"avatar_hd": "https://ww1.sinaimg.cn/orj480/77b4bd05jw8f44h2k95r8j20990dw0u4.jpg",
"badge": {
"unread_pool": 1,
"unread_pool_ext": 1,
"user_name_certificate": 1
},
"statuses_count": 90,
"verified": false,
"verified_type": -1,
"gender": "m",
"mbtype": 0,
"svip": 0,
"urank": 11,
"mbrank": 0,
"followers_count_str": "122",
"verified_reason": "",
"like": false,
"like_me": false,
"special_follow": false
},
"retweeted_status": {
"visible": {
"type": 0,
"list_id": 3,
"list_idstr": "3"
},
"created_at": "Mon Nov 19 15:32:58 +0800 2012",
"id": "3514100782679935",
"mid": "3514100782679935",
"text": "抱歉,根据作者设置的微博可见时间范围,此微博已不可见。 ",
"edit_config": {
"edited": false
},
"user": null,
"bid": "z5UPcbfaL",
"source": ""
},
"reposts_count": 0,
"comments_count": 0,
"reprint_cmt_count": 0,
"attitudes_count": 0,
"mixed_count": 0,
"pending_approval_count": 0,
"isLongText": false,
"show_mlevel": 0,
"darwin_tags": [],
"ad_marked": false,
"mblogtype": 0,
"item_category": "status",
"rid": "0_0_50_165731835786324711_0_0_0",
"extern_safe": 0,
"number_display_strategy": {
"apply_scenario_flag": 19,
"display_text_min_number": 1000000,
"display_text": "100万+"
},
"content_auth": 0,
"is_show_mixed": false,
"comment_manage_info": {
"comment_manage_button": 1,
"comment_permission_type": 0,
"approval_comment_type": 0,
"comment_sort_type": 0
},
"pic_num": 0,
"mlevel": 0,
"detail_bottom_bar": 0,
"analysis_extra": "mblog_rt_mid:3514100782679935",
"mblog_menu_new_style": 0,
"edit_config": {
"edited": false
},
"reads_count": 0,
"raw_text": "转发微博",
"bid": "z5XWQC3VN"
}
可以看到,这个元素里有个重要的字段叫 mblog。展开 mblog 能发现,里面包含了微博的一些信息,像 attitudes_count(点赞数)、comments_count(评论数)、reposts_count(转发数)、created_at(发布时间)、text(微博正文)等,而且这些信息都是格式化好的。
这样一来,我们访问一次这个接口,就能得到 10 条微博的数据,而且每次请求时,只需要改变 since_id 参数的值就行。
但是想获取到所有的微博数据, since_id是变化的,这个要深入了解 since_id的动态变化算法才行。(有反爬虫限制)
四、Ajax抓取实战
现在,我们用程序来模拟这些 Ajax 请求,把我的某一页10条的微博都爬取下来。我们先把请求头的信息拷贝下来,请求数据时需要按照此格式内容构造。请求头如下:
Request URL:
https://m.weibo.cn/api/container/getIndex?type=uid&value=2008333573&containerid=1076032008333573&since_id=3514220849071579
Request Method:
GET
Status Code:
200 OK (from service worker)
Referrer Policy:
strict-origin-when-cross-origin
content-encoding:
gzip
content-security-policy:
upgrade-insecure-requests
content-type:
application/json; charset=utf-8
date:
Mon, 14 Apr 2025 13:21:05 GMT
lb:
49.7.37.75
proc_node:
mweibo-h5-v8-1-web-hj4-5cf9d75bd9-w9pnz
server:
SHANHAI-SERVERssl_node:
msre-10-185-8-138.yf.intra.weibo.cn
vary:
Accept-Encoding
x-log-uid:
2008333573
x-powered-by:
PHP/7.2.1
accept:
application/json, text/plain, */*
mweibo-pwa:
1
referer:
https://m.weibo.cn/u/2008333573
sec-ch-ua:
"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"
sec-ch-ua-mobile:
?0
sec-ch-ua-platform:
"Windows"
user-agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
x-requested-with:
XMLHttpRequest
x-xsrf-token:
e8e409
首先,定义一个函数,用来获取每次请求的结果。因为请求时since_id 参数是会变化的,所以我们把它作为函数的参数传进去。
先定义了 base_url,它是请求 URL 的前半部分。然后构造了一个参数字典,其中 type、value 和 containerid 这几个参数的值是固定的,page 是会变化的参数。接着调用 urlencode 方法,把参数字典转化成 URL 的 GET 请求参数形式。再把 base_url 和参数拼起来,得到一个完整的新 URL。之后,用 requests 库去请求这个链接,并且带上 headers 参数。请求后判断响应的状态码,如果是 200,就调用 json 方法把响应内容解析成 JSON 格式并返回,否则不返回任何东西。要是请求过程中出了异常,就捕获异常并输出异常信息。
然后,我们要定义一个解析函数,从请求结果里提取出我们想要的信息。比如这次我们想保存微博的 id、正文、点赞数、评论数和转发数这些内容。可以先遍历 cards 列表,然后从 mblog 里获取各个信息,再赋值给一个新的字典返回。
这里借助 pyquery 库,把微博正文里的 HTML 标签去掉了。
最后,我们特定爬取某一页内容,把提取到的结果打印输出,完整代码如下:
import requests
from urllib.parse import urlencode
from pyquery import PyQuery as pqbase_url = 'https://m.weibo.cn/api/container/getIndex?'
headers = {'Host': 'm.weibo.cn','Referer': 'https://m.weibo.cn/u/2008333573','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36','X-Requested-With': 'XMLHttpRequest','Accept': 'application/json, text/plain, */*','Sec-Ch-Ua': '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"','Sec-Ch-Ua-Mobile': '?0','Sec-Ch-Ua-Platform': '"Windows"','Mweibo-Pwa': '1','X-Xsrf-Token': 'e8e409'
}def get_page(page):params = {'type': 'uid','value': '2008333573','containerid': '1076032008333573','since_id': page}url = base_url + urlencode(params)try:response = requests.get(url, headers=headers)if response.status_code == 200:return response.json(), pageexcept requests.ConnectionError as e:print('Error', e.args)def parse_page(json, page: int):if json:items = json.get('data').get('cards')for index, item in enumerate(items):if page == 1 and index == 1:continueelse:item = item.get('mblog', {})weibo = {}weibo['id'] = item.get('id')weibo['text'] = pq(item.get('text')).text()weibo['attitudes'] = item.get('attitudes_count')weibo['comments'] = item.get('comments_count')weibo['reposts'] = item.get('reposts_count')yield weiboif __name__ == '__main__':json = get_page(3514220849071579)results = parse_page(*json)for result in results:print(result)
这样,我们通过分析 Ajax 请求,编写爬虫程序,成功把微博列表数据爬取下来了。
这一节主要是为了演示如何模拟 Ajax 请求,爬取到的结果不是重点。这个程序还有很多可以改进的地方,比如动态计算页码、处理微博查看全文的情况等等。要是你有兴趣,可以自己动手试试看。通过这个例子,我们学会了怎么分析 Ajax 请求,以及怎么用程序模拟请求来抓取数据。掌握了这些原理,下一节的 Ajax 实战操作就会更轻松了。
参考学习书籍:Python 3网络爬虫开发实战
相关文章:
Python爬虫第14节-如何爬取Ajax的数据
目录 前言 一、什么是Ajax 1.1 具体举例 1.2 基本原理 二、Ajax的分析 2.1 查看请求 2.2 过滤请求 三、解析提取Ajax 结果 3.1 分析请求 3.2 分析响应 四、Ajax抓取实战 前言 咱们在使用requests抓取网页的时候,常常会发现,得到的结果和在浏览…...
mac上面使用zip命令压缩一劳永逸
问题 需要将当前目录的文件和目录(包含隐藏目录)都要压缩近一个zip包,但同时部分目录我不想压缩进去例如:.idea这个种idea的配置目录就不想压缩进zip包。 命令 zip -r flask-dev.zip . -x "*.idea*"-r:递归目录.:当前…...
错误地使用了 app.use() 来注册全局组件
我是import globalComponent from "/components"; /* eslint-disable */ // ts-nocheck // Generated by unplugin-vue-components // Read more: https://github.com/vuejs/core/pull/3399 export {}; /* prettier-ignore */ declare module vue { export interface…...
Python Django基于协同过滤算法的招聘信息推荐系统【附源码、文档说明】
博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…...
鹰角:EMR Serverless Spark 在《明日方舟》游戏业务的应用
作者:鹰角网络高级大数据研发 茅旭辉 背景介绍 鹰角网络是一家年轻且富有创新的游戏公司,致力于开发充满挑战性和艺术价值的游戏产品。公司目前涵盖了游戏开发、运营和发行的全生命周期业务。随着业务的扩展,鹰角网络从单一爆款游戏发展到多…...
C语言学习之两个数值交换的算法
前言:本篇文章仅仅是作为作者复习使用 在C语言中,交换两个两个变量的数值是很常见的应用。在学习到指针的时候,我们已经掌握了几种交换的算法了。今天我来做一个小汇总 1创建第三个变量 缺点:需要创造第三个变量 2加减交换 缺点…...
CExercise_13_1排序算法_2归并排序
题目:CExercise_ 请手动实现归并排序算法: void merge_sort(int arr[], int len) 如果学有余力,不妨尝试一下多种临时数组的方式: 1.局部变量数组 2.全局变量数组 3.堆数组 关键点 分析: : 代码 代码块解决…...
富斯i6遥控器,无法切换通道解决办法
开机后长按【OK】键,进入设置 按【DOWN】选择【setup】 点击【ok】进入设置 再点击【OK】进入Reverse 将2设置为下,长按【cancel】保存,返回到设置 进入【Aux.channels】 将第二行【Source】设置为【Source SwC】,长按【CANCEL】保存并返回。…...
Maven 编译指定模版
背景 基于SpringCloud 做的微服务项目,很多都是依赖公共模块下的包,并且多模板都是在一个项目下的。 问题 每次打包都很编译整个项目下的所有模块。这样太耗时间了,把流水线的时间拖的太长了。 解决方案 在maven打包时,我们选…...
solr安装及ik中文分词器配置
提示:solr9.x版本需要jdk17,solr8.x版本需要jdk8 1、Solr 简介 Solr 是Apache 下的一个顶级开源项目,采用 Java 开发,它是基于 Lucene 的全文搜索服务器。Solr 提供了比 Lucene 更为丰富的查询语句,同时实现了可配置、…...
详解LeetCode中用字符串实现整数相加,字符串转整数及其溢出处理详解
目录 题目背景 代码整体逻辑 变量初始化 逐位相加过程 处理最后进位 结果反转 示例演示 总结 在LeetCode中,有一道经典的算法题是实现两个字符串形式的非负整数相加,今天我们就来深入分析一段用C实现该功能的代码,探究其背后的逻辑与…...
vue学习笔记06
学习的课程地址:老杜Vue视频教程,Vue2,Vue3实战精讲,一套通关vue_哔哩哔哩_bilibili 1、vue程序初体验 2、vue核心技术(基础) 3、Vue组件化 前面参见: vue学习笔记01 vue学习笔记02 vue学习笔记03 vue学习笔记…...
如何查看自己抖音的IP属地?详细教程及如何修改
在当今互联网时代,IP属地信息已成为各大社交平台(如抖音、微博、快手等)展示用户真实网络位置的重要功能。以下是关于如何查看抖音IP属地的详细教程及常见问题解答,帮助您快速了解相关信息: 一、如何查看抖音账号的IP属…...
熟悉Linux下的编程
可能 目录 熟悉Linux下Python编程的含义及与非Linux环境编程的区别 一、核心含义解析 二、与非Linux环境的关键区别 三、典型应用场景对比 四、能力培养建议 openfoem的下载之路: 方法一:使用cd命令 方法二:使用快捷方式 方法三&am…...
Uniapp:获取当前定位坐标
目录 一、出现场景二、具体使用 一、出现场景 在项目的开发中,会出现打卡、定位当前位置的功能,那我们如何获取当前位置呢?这就需要使用getLocation来获取当前位置坐标 二、具体使用 uni.getLocation({type: wgs84, // 返回可以用于uni.op…...
GitHub实用手册
文章目录 一、GitHub 的定义二、GitHub 的主要功能三、GitHub 的优势四、GitHub 的使用相关工具GitSourcetreeGithub-Desktop 一、GitHub 的定义 GitHub 是一个基于 Git 的分布式版本控制系统,它允许开发者在本地和远程仓库中管理代码版本,支持多人协作…...
【从零实现高并发内存池】Central Cache从理解设计到全面实现
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
Dijkstra算法求解最短路径—— 从零开始的图论讲解(2)
前言 在本系列第一期:从零开始的图论讲解(1)——图的概念,图的存储,图的遍历与图的拓扑排序-CSDN博客 笔者给大家介绍了 图的概念,如何存图,如何简单遍历图,已经什么是图的拓扑排序 按照之前的学习规划,今天笔者将继续带大家深入了解图论中的一个核心问题&#x…...
Spring AI 发布了它的 1.0.0 版本的第七个里程碑(M7)
Spring AI 发布了它的 1.0.0 版本的第七个里程碑(M7),下个月就是 RC1,紧接着就是 GA!,对于我们 Java 开发者来说,这绝对是个值得关注的好消息! 但是对于 Java 学习者来说,…...
如何从 GitHub 镜像仓库到极狐GitLab?
最近 GitHub 封禁中国用户的事情闹得沸沸扬扬,虽然官方发布的报道说中国用户被限制登录是因为配置错误导致,已经撤回了更新,中国用户已经可以正常使用。但是这就像横在国内开发者和企业头上的“达摩克利斯之剑”。为了避免 GitHub 不可用而带…...
大象机器人推出myCobot 280 RDK X5,携手地瓜机器人共建智能教育机
摘要 大象机器人全新推出轻量级高性能教育机械臂 myCobot 280 RDK X5,该产品集成地瓜机器人 RDK X5 开发者套件,深度整合双方在硬件研发与智能计算领域的技术优势,实现芯片架构、软件算法、硬件结构的全栈自主研发。作为国内教育机器人生态合…...
在Android Studio中,`Settings`里的Gradle路径、环境变量以及`gradle - wrapper.properties`文件关联
在Android Studio中,Settings里的Gradle路径、环境变量以及gradle - wrapper.properties文件关联 Android Studio中Settings里的Gradle路径 在Android Studio的Settings(Preferences ) -> Build, Execution, Deployment -> Build Tools -> Gradle 中: Use defau…...
用react 写一个可左右滑动的柱状图
效果图 目录 效果图 ✅ 项目结构 🚀 创建项目步骤 1️⃣ 打开终端或命令行,创建新项目: 2️⃣ 安装 recharts 图表库: 3️⃣ 替换默认代码: 4️⃣ 启动项目: ✅ 项目结构 scrollable-bar-chart/ ├…...
【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——MIPI LCD测试
1)实验平台:正点原子ATK-DLMP257B开发板 2)浏览产品:www.alientek.com 3)全套实验源码手册视频下载:正点原子资料下载中心 文章目录 第四章 ATK-DLMP257B功能测试——MIPI LCD测试4.3 MIPI LCD测试4.3.1 使…...
【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——RS485串口测试
1)实验平台:正点原子ATK-DLMP257B开发板 2)浏览产品:www.alientek.com 3)全套实验源码手册视频下载:正点原子资料下载中心 文章目录 第四章 ATK-DLMP257B功能测试——RS485串口测试 第四章 ATK-DLMP257B功能…...
Sui 的工具生态简化了游戏开发者的 Web3 集成流程
希望利用 Web3 独特协同效应的游戏开发者,常常在强大的区块链功能与流畅的游戏体验之间难以权衡。许多区块链方案要求大幅重构游戏基础架构,增加了开发难度,甚至需要学习全新的智能合约语言。而 Sui 通过直观的工具消除这一阻力,使…...
Vue 3 的组合式 API-hooks
Vue 3 的组合式 API 组合式 API 是 Vue 3 的核心特性之一,它允许开发者将组件的逻辑拆分为可复用的函数。组合式 API 的主要特点是 逻辑复用:将逻辑提取到独立的函数中,方便在多个组件中复用。组织清晰:将相关的逻辑分组&#x…...
AOSP Android14 Launcher3——底部任务栏Taskbar详解
前言:Launcher3中底部Taskbar和Navbar,或者说中文里面的术语导航栏,这几个词是很容易让人混淆的地方。本文要介绍的是Taskbar。从字面上意思来看,Taskbar就是任务栏,任务栏是Launcher3中一个重要的组件,尤其…...
QGraphicsView、QGraphicsScene和QGraphicsItem图形视图框架(五)QGraphicsView的缩放和移动
QGraphicsView自带滚动条的显示,但是大部分的需求样式都不需要滚动条,并且要通过鼠标来控制视图的缩放和移动。需要重写QGraphicsView实现。 一、相关函数 1.scale void QGraphicsView::scale(qreal sx, qreal sy) 按(sx,sy&…...
算法——果蝇算法
果蝇算法(Fruit Fly Optimization Algorithm,FOA)是一种受果蝇觅食行为启发而开发的群智能优化算法。以下从算法原理、算法流程、算法特点等方面为你详细讲述: 算法原理 果蝇本身具有优于其他物种的嗅觉和视觉。在觅食过程中&am…...
重返JAVA之路——图书管理系统
目录 一、功能介绍 二、设计模块 三、系统构建 1.book模块 2.operation模块 输入循环和验证 查找图书并处理借阅状态 未找到图书的处理 查找删除图书功能实现 未找到图书的处理 图书查找与归还 work方法实现图书信息输出 3. user模块实现 四、主菜单 一、功能介绍 …...
【16】数据结构之基于树的排序算法篇章
目录标题 选择排序简单选择排序树形选择排序 堆排序堆的定义Heap小跟堆大根堆堆的存储堆的代码设计堆排序的代码设计 排序算法综合比较 选择排序 基本思想:从待排序的序列中选出最大值或最小值,交换该元素与待排序序列的头部元素,对剩下的元…...
Uniapp:确认框
目录 一、 出现场景二、 效果展示三、具体使用 一、 出现场景 在项目的开发中,会经常出现删除数据的情况,如果直接删除的话,可能会存在误删,用户体验不好,所以需要增加一个消息提示,提醒用户是否删除。 二…...
pyswmm实现洪涝模拟
准备好.inp文件作为SWMM模型输入,调用pyswmm模块执行模拟,返回节点溢流量(flooding)作为积水量的初步表征。 代码: from pyswmm import Simulation, Nodes import pandas as pddef run_swmm_simulation(inp_file, ou…...
My Diary Pro:记录生活,珍藏回忆
我的日记My Diary Pro是一个非常好用的手机日记软件,可以使用它来记录每日生活日常,不少的用户可能都知道在生活之中可能会发生一些比较的重要的事情,实际上我们都可以将这些内容记录下来。包括个人观点,旅行游记,心情…...
CSRF(跨站请求伪造)漏洞概述
CSRF(跨站请求伪造)漏洞概述 一、什么是 CSRF 攻击者诱导已登录用户在不知情的情况下,对受信任网站执行未授权操作。 简单说:你登录着网站A,攻击者诱导你访问某个恶意链接,使网站A误以为是你自己发出的操作(比…...
[Java实战经验]对象拷贝
目录 谨慎重写clone方法重写clone()支持深拷贝带来的问题 合适的深拷贝 首先,对于不可变的类,我们不应该实现Cloneable接口,因为不可变类不需要拷贝,直接引用即可,实现Cloneable接口只会造成浪费。 对于Java可变类来说…...
WAF防火墙:构筑Web应用安全的“隐形护盾”
在数字化时代,Web应用已成为企业服务与用户交互的核心窗口。然而,随之而来的SQL注入、跨站脚本攻击(XSS)、DDoS攻击等威胁,时刻考验着网站的安全防线。Web应用防火墙(WAF)作为关键防护工具&…...
开源智慧巡检——无人机油田AI视频监控的未来之力
油田巡检,关乎能源命脉,却常受困于广袤地形、高危环境和人工效率瓶颈。管道泄漏、设备故障、非法闯入——这些隐患稍有疏忽,便可能酿成大患。传统巡检已无法满足现代油田对安全与效率的需求,而无人机油田巡检系统正以智能化之力重…...
【2025年泰迪杯数据挖掘挑战赛】B题 完整论文 模型建立与求解
目录 2025年泰迪杯数据挖掘挑战赛 B题完整论文:建模与求解 Matlab代码一、问题重述二、模型假设与符号说明2.1 模型基本假设2.2 符号说明 三、数据预处理**问题一:志愿者身体活动信息的统计分析****问题二:身体活动MET值的实时估计模型构建**…...
Chromium 134 编译指南 macOS篇:安装 Xcode(二)
1. 引言 在Chromium开发的征程中,为macOS平台构建正确的开发环境是成功编译的关键基础。继上一篇系统环境准备后,本文将重点介绍Xcode的安装与配置过程。作为macOS上不可或缺的集成开发环境(IDE),Xcode为Chromium 134的编译提供了必要的编译…...
软件定义网络(SDN):重塑未来网络的革命性架构
在当今数字化时代,网络已成为企业、云计算、5G通信和物联网(IoT)的核心基础设施。然而,传统网络架构由于其封闭、静态和分布式的特性,难以应对快速变化的业务需求。软件定义网络(Software-Defined Networki…...
Java虚拟机面试题:类加载机制
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
OCCT 入门(3)核心模块与架构
文章目录 一、核心模块与架构1、架构概述2、核心模块3、数据流转3.1、几何创建(Geometric Primitives)3.2、拓扑构建(Topology Construction)3.3、模型处理(Modeling Algorithms)3.4、可视化(Vi…...
MAC-需求:10万订单异步执行库存扣减、短信通知。
批量任务并行处理 实现,通过拆分任务、异步执行和线程池管理提升处理。 10万订单异步处理方案设计 基于图中代码的批量处理框架,结合订单业务需求,以下是 库存扣减与短信通知的异步实现: 1. 代码实现(基于原有框架改造) @Service public…...
ArrayList vs LinkedList,HashMap vs TreeMap:如何选择最适合的集合类?
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 在 Java 开发中,集合类的选择直接影响程序的性能和代码的可维护性。不同的数据结构适用于不同的场景,盲目使用可能导致内存浪费、性能…...
使用Form.List且有Select组件
当在使用Form.List组件,且组件中有Select选项时,针对每一次选择,都要过滤掉那些已经选择过的选项,可能遇到的问题: 直接过滤会将每一个Select中的options选项都过滤掉,无法正常展示选择的选项 解决办法&a…...
大数据学习笔记
文章目录 1. 大数据概述1.1 大数据的特性1.2 大数据技术生态1.2.1 Hadoop 的概念特性1.2.2 Hadoop生态圈 — 核心组件与技术栈1.2.3 Hadoop生态演进趋势 2. 数据处理流程与技术栈2.1 数据采集2.1.1 日志采集工具2.1.2 实时数据流2.1.3 数据迁移 2.2 数据预处理2.2.1 批处理2.2.…...
Obsidian 文件夹体系构建 -INKA
Obsidian 文件夹体系构建 -INKA 本篇文章主要分享一下自己折腾学习实践过的 INKA 框架方法。原地址:Obsidian文件夹体系构建–INKA。 文章目录 Obsidian 文件夹体系构建 -INKA前言INKA简介INKA 理论最佳实践实际应用 反思 前言 上文 Obsidian文件夹体系构建-ACCES…...
QML与C++:基于ListView调用外部模型进行增删改查(性能优化版)
目录 引言相关阅读工程结构数据模型设计DataModel 类ContactProxyModel 类 为什么使用QSortFilterProxyModel?应用初始化与模型连接UI实现 性能分析与优化运行效果扩展思考总结下载链接 引言 在上一篇中介绍了基于ListView调用外部模型进行增删改查,本文…...