爬虫 — App 爬虫(二)
目录
- 一、Appium介绍
- 二、node.js 安装
- 三、Java 的 SDK 安装以及配置
- 1、安装步骤
- 2、配置环境变量
- 四、安卓环境的配置
- 1、配置环境变量
- 五、Appium 安装
- 1、安装
- 2、打开 APP
- 3、使用
- 六、Appium 使用
- 1、定位数据(方法一,不常用)
- 2、定位数据(方法二,常用)
- 3、练习
- 4、界面滑动
- 七、案例
一、Appium介绍
类似于 selenium,找包比较困难,加密参数比较难解的时候使用。
所需环境
-
node.js
-
Java 的 SDK
-
安卓的 SDK
-
Appium 应用程序
-
模拟器
二、node.js 安装
node.js 下载官网
安装步骤
1、点击 Next;

2、选中勾选框后,点击 Next;

3、选中安装路径后,点击 Next;

4、点击 Next;

5、点击 Next;

6、点击 Install;

7、点击 Finish;

8、安装完成。
9、验证安装。
按 win + R,输入 cmd 后,按回车。

在终端窗口输入以下命令:
node -v 显示安装的 node.js 版本
npm -v 显示安装的 npm 版本

三、Java 的 SDK 安装以及配置
点击进入官网下载
点击进入百度网盘下载,版本:jdk-8u211-windows-x64
1、安装步骤
1、点击“下一步”;

2、更改安装路径后,点击“确定”;

3、点击“下一步”;

4、更改安装目录后,点击“下一步”;

5、点击“关闭”;

2、配置环境变量
1、在桌面上“此电脑”图标上右击,选择“属性”,选择“高级系统设置”;
2、选择“高级”,点击“环境变量”;

3、找到系统变量,点击“新建”;

4、填入变量名和变量值,变量值为安装路径,点击“确定”;
变量名输入:JAVA_HOME
变量值输入:E:\Install\Java\jdk1.8.0_211

5、还需要新建一个变量值,点击“新建”;

6、填入变量名和变量值,点击“确定”;
变量名输入:CLASS_PATH
变量值输入:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar

7、选中“Path”,点击“编辑”;

8、点击“新建”,添加一个路径:%JAVA_HOME%\bin 后,点击“确定”;

9、验证是否安装成功,打开终端,输入 java -version,出现对应的版本号就可以了。

四、安卓环境的配置
点击进入下载地址
下载后解压到任意目录下
1、配置环境变量
1、在桌面上“此电脑”图标上右击,选择“属性”,选择“高级系统设置”;
2、选择“高级”,点击“环境变量”;

3、找到系统变量,点击“新建”;

4、填入变量名和变量值,变量值为安装路径,点击“确定”;
变量名输入:ANDROID_HOME
变量值输入:E:\Install\androidsdk

5、选中“Path”,点击“编辑”;

6、点击“新建”,编辑系统环境的 Path 后,点击“确定”;
%ANDROID_HOME%\platform-tools
%ANDROID_HOME%\tools

7、验证是否配置成功,打开终端,输入adb。

adb:安卓调试桥
Android 环境和开发环境之间桥梁
可以让用户在电脑上对手机进行全面的操作
五、Appium 安装
点击进入下载地址
1、安装
1、按需求选择后,点击“安装”;

2、点击“完成”;

2、打开 APP
方法一:使用 Appium 的内置驱动打开 APP
方法二:使用 Python 代码打开 APP
-
在终端查看 selenium 版本
命令:pip show selenium
-
版本低于 4.1.1 的需要升级一下(需要先把 Python 升级到 3.7 以上版本)
命令:pip install selenium==4.1.1
-
安装 Appium 第三方库
命令:pip install appium-python-client
如果报以下错误
WARNING: You are using pip version 20.1.1; however, version 23.1.2 is available.
You should consider upgrading via the ‘e:\install\python37\python.exe -m pip install --upgrade pip’ command.可在终端输入命令:python.exe -m pip install --upgrade pip
3、使用
1、启动模拟器,新开一个模拟器(专门用来采用 Appium 来爬取数据);
2、进去模拟器后,进入“工具”,进入“设置”,进入“关于平板电脑”,不停的点击版本号,直到出现开发者选项,打开 usb 调试;
3、重启模拟器 ;
4、双击打开安装好的 Appium,输入本地 IP 地址 127.0.0.1 后,点击“Start Server v1.15.1”;

5、验证 Appium 是否可以操作模拟器;
命令:adb devices -l

如果报以下错误
adb server version (36) doesn’t match this client (41); killing…
原因:由于 SDK 里 adb 和夜神模拟器的 adb 版本不匹配导致
解决方法:
1、找到 androidsdk 文件夹所在目录下的 platform-tools 文件夹下的 adb.exe,复制到桌面,重命名为 nox_adb.exe
2、找到夜神模拟器安装文件夹所在的目录下的 bin 文件夹下的 nox_adb.exe,重命名为 nox_adb_old.exe
3、把桌面上的 nox_adb.exe 拷贝到夜神模拟器的 bin 文件夹下
4、重启模拟器
6、在模拟器里打开需要获取包名和界面名的页面;
在终端输入命令:
adb shell dumpsys window windows | findstr mFocusedApp
输出结果:
mFocusedApp=AppWindowToken{c618cec token=Token{577693eActivityRecord{3fe15f9 u0 com.android.browser/.BrowserActivity t7}}}
包名:com.android.browser
界面名:.BrowserActivity
7、运行代码;
from appium import webdriver # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序# 创建一个字典用于存储配置参数
caps = dict()
# 配置连接参数
# 设置系统为 Android
caps['platformName'] = 'Android'
# 设置平台版本为 7.1.2(模拟器-关于平板-版本号)
caps['platformVersion'] = '7.1.2'
# 设置设备名称为 Android(可以换)
caps['deviceName'] = 'Android'
# 设置应用程序的包名
caps['appPackage'] = 'com.android.browser'
# 设置应用程序的界面名
caps['appActivity'] = '.BrowserActivity'
# 有需要输入中文,需要设置为 True
caps['unicodeKeyboard'] = True
# 重置键盘设置,恢复原来的输入法
caps['resetKeyboard'] = True
# 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
caps['noReset'] = True
# 设置新命令的超时时间为 6000 毫秒
caps['newCommandTimeout'] = 6000
# 设置自动化引擎为 UiAutomator2
caps['automationName'] = 'UiAutomator2'# 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
# 打开网址
driver.get('https://www.baidu.com/')
六、Appium 使用
1、定位数据(方法一,不常用)
1、Appium 先停止服务并且完全退出;
2、找到 androidsdk 文件夹,点击 tools 文件夹,点击 bin 文件夹,双击 uiautomatorviewer.bat 文件;
3、点击图标;

4、找到需要定位的数据。

2、定位数据(方法二,常用)
1、打开 Appium,输入本地 IP 地址 127.0.0.1 后,点击“Start Server v1.15.1”;

2、点击图标;

3、按照代码添加参数;
# 配置连接参数
# 设置系统为 Android
caps['platformName'] = 'Android'
# 设置平台版本为 7.1.2(模拟器-关于平板-版本号)
caps['platformVersion'] = '7.1.2'
# 设置设备名称为 Android(可以换)
caps['deviceName'] = 'Android'
# 设置应用程序的包名
caps['appPackage'] = 'com.android.browser'
# 设置应用程序的界面名
caps['appActivity'] = '.BrowserActivity'
# 有需要输入中文,需要设置为 True
caps['unicodeKeyboard'] = True
# 重置键盘设置,恢复原来的输入法
caps['resetKeyboard'] = True
# 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
caps['noReset'] = True
# 设置新命令的超时时间为 6000 毫秒
caps['newCommandTimeout'] = 6000
# 设置自动化引擎为 UiAutomator2
caps['automationName'] = 'UiAutomator2'



3、练习
需求:打开浏览器,地址栏输入 www.douban.com 后按回车
分析:
1、打开浏览器
2、鼠标点击地址栏
3、输入网址
4、回车
代码实现
from appium import webdriver # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序
from appium.webdriver.extensions.android.nativekey import AndroidKey # 导入 AndroidKey 模块,用于模拟 Android 设备的按键操作
from selenium.webdriver.common.by import By # 导入 By 模块,用于定位元素# 创建一个字典用于存储配置参数
caps = dict()
# 配置连接参数
# 设置系统为 Android
caps['platformName'] = 'Android'
# 设置平台版本为 7.1.2(模拟器-关于平板-版本号)
caps['platformVersion'] = '7.1.2'
# 设置设备名称为 Android(可以换)
caps['deviceName'] = 'Android'
# 设置应用程序的包名--浏览器
caps['appPackage'] = 'com.android.browser'
# 设置应用程序的界面名
caps['appActivity'] = '.BrowserActivity'
# 有需要输入中文,需要设置为 True
caps['unicodeKeyboard'] = True
# 重置键盘设置,恢复原来的输入法
caps['resetKeyboard'] = True
# 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
caps['noReset'] = True
# 设置新命令的超时时间为 6000 毫秒
caps['newCommandTimeout'] = 6000
# 设置自动化引擎为 UiAutomator2
caps['automationName'] = 'UiAutomator2'# 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
# 定位输入框元素
input_tag = driver.find_element(By.ID, 'com.android.browser:id/url')
# 进行点击操作
input_tag.click()
# 在输入框中输入指定的网址
input_tag.send_keys('www.douban.com')
# 模拟按下 ENTER 键
driver.press_keycode(AndroidKey.ENTER)
4、界面滑动
分为:
从一个元素滑动到另外一个元素
从一个位置滑动到另外一个位置
需求:进入“设置”界面,从“WLAN”滑动到“声音”
分析:
1、在模拟器里打开“设置”界面;
2、获取“设置”界面的包名和界面名;
在终端输入命令:
adb shell dumpsys window windows | findstr mFocusedApp
输出结果:
mFocusedApp=AppWindowToken{b9a8e16 token=Token{2ed7d8 ActivityRecord{a2e16bb u0 com.android.settings/.Settings t13}}}
包名:com.android.settings
界面名:.Settings
from appium import webdriver # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序# 创建一个字典用于存储配置参数
caps = dict()
# 配置连接参数
# 设置系统为 Android
caps['platformName'] = 'Android'
# 设置平台版本为 7.1.1(模拟器-关于平板-版本号)
caps['platformVersion'] = '7.1.1'
# 设置设备名称为 Android(可以换)
caps['deviceName'] = 'Android'
# 设置应用程序的包名--设置
caps['appPackage'] = 'com.android.settings'
# 设置应用程序的界面名
caps['appActivity'] = '.Settings'
# 有需要输入中文,需要设置为 True
caps['unicodeKeyboard'] = True
# 重置键盘设置,恢复原来的输入法
caps['resetKeyboard'] = True
# 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
caps['noReset'] = True
# 设置新命令的超时时间为 6000 毫秒
caps['newCommandTimeout'] = 6000
# 设置自动化引擎为 UiAutomator2
caps['automationName'] = 'UiAutomator2'# 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
3、在 Appium 里输入配置参数,保存好后,运行;
4、定位数据“WLAN”和“声音”的位置,然后滑动;
from appium import webdriver # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序
from selenium.webdriver.common.by import By # 导入 By 模块,用于定位元素# 创建一个字典用于存储配置参数
caps = dict()
# 配置连接参数
# 设置系统为 Android
caps['platformName'] = 'Android'
# 设置平台版本为 7.1.1(模拟器-关于平板-版本号)
caps['platformVersion'] = '7.1.1'
# 设置设备名称为 Android(可以换)
caps['deviceName'] = 'Android'
# 设置应用程序的包名--设置
caps['appPackage'] = 'com.android.settings'
# 设置应用程序的界面名
caps['appActivity'] = '.Settings'
# 有需要输入中文,需要设置为 True
caps['unicodeKeyboard'] = True
# 重置键盘设置,恢复原来的输入法
caps['resetKeyboard'] = True
# 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
caps['noReset'] = True
# 设置新命令的超时时间为 6000 毫秒
caps['newCommandTimeout'] = 6000
# 设置自动化引擎为 UiAutomator2
caps['automationName'] = 'UiAutomator2'# 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
# 定位元素--WLAN
WLAN = driver.find_element(By.XPATH, '//*[@text="WLAN"]')
# 定位元素--声音
sy = driver.find_element(By.XPATH, '//*[@text="声音"]')
# 滑动
# 从一个元素滑动到另外一个元素
# 手的操作是往上,内容是往下加载
driver.drag_and_drop(sy, WLAN)
注意:
如果要滑动到的位置不在第一页里,直接滑动会报错
需要滑动到第一页的最后的位置,等下一页的内容加载出来,才能再滑动
七、案例
目标 APP:笔趣阁
需求:爬取排行榜的标题及简介
分析
1、打开笔趣阁 APP
2、点击榜单
3、点击热搜榜
4、获取第一页后,滑动,获取第二页数据,滑动,直到获取50条数据
5、多次滑动,可以用循环
6、不通过直接获取包名和界面名来打开笔趣阁,可以直接通过定位 APP 位置
代码实现
import json # 导入 json 模块,用于处理 JSON 格式的数据
import time # 导入 time 模块,用于添加延时等待
from appium import webdriver # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序
from selenium.webdriver.common.by import By # 导入 By 模块,用于定位元素# 创建一个字典用于存储配置参数
caps = dict()
# 配置连接参数
# 设置系统为 Android
caps['platformName'] = 'Android'
# 设置平台版本为 7.1.1(模拟器-关于平板-版本号)
caps['platformVersion'] = '7.1.1'
# 设置设备名称为 Android(可以换)
caps['deviceName'] = 'Android'
# 有需要输入中文,需要设置为 True
caps['unicodeKeyboard'] = True
# 重置键盘设置,恢复原来的输入法
caps['resetKeyboard'] = True
# 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
caps['noReset'] = True
# 设置新命令的超时时间为 6000 毫秒
caps['newCommandTimeout'] = 6000
# 设置自动化引擎为 UiAutomator2
caps['automationName'] = 'UiAutomator2'# 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
# 定位笔趣阁 App,并点击
driver.find_element(By.XPATH, '//android.widget.TextView[@content-desc="笔趣阁"]').click()
# 等待3秒
time.sleep(3)
# 点击榜单
driver.find_element(By.XPATH, '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.TabHost/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout[1]/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.widget.ImageView').click()
# 等待2秒
time.sleep(2)
# 点击热搜榜
driver.find_element(By.ID, 'com.bqg.ddnoverl:id/tvAiRkName').click()
# 创建一个空集合,用于存储数据项,自动去重
data = set()
# 获取屏幕的尺寸
window_size = driver.get_window_size()
# 高跟宽
height, width = window_size.get('height'), window_size.get('width')
while True:# 等待3秒time.sleep(3)# 获取多个榜单元素contents = driver.find_elements(By.XPATH, '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.LinearLayout')# 打印榜单元素数量print(len(contents))# 循环获取数据for content in contents:try:# 创建一个空字典,用于存储每个内容项的信息item = {}# 标题item['title'] = content.find_element(By.ID, 'com.bqg.ddnoverl:id/tvClTitle').text# 简介item['content'] = content.find_element(By.ID, 'com.bqg.ddnoverl:id/tvClDesc').text# 打印数据print(item)# 将数据转换为 JSON 格式并添加到集合中# 集合里面的添加是不能直接添加字典的,需要转换类型data.add(json.dumps(item, ensure_ascii=False))except:# 处理数据异常情况print('数据有误')if len(data) < 50:# 在应用中进行滑动操作,从屏幕的上部中间位置向下滑动到屏幕的下部中间位置,持续时间为1000毫秒driver.swipe(width * 0.5, height * 0.7, width * 0.5, height * 0.2, 1000)# 打印提示print("滑动成功")else:# 数据达到50个,跳出循环break
# 打印最终的数据集合
print(data)
记录学习过程,欢迎讨论交流,尊重原创,转载请注明出处~
相关文章:
爬虫 — App 爬虫(二)
目录 一、Appium介绍二、node.js 安装三、Java 的 SDK 安装以及配置1、安装步骤2、配置环境变量 四、安卓环境的配置1、配置环境变量 五、Appium 安装1、安装2、打开 APP3、使用 六、Appium 使用1、定位数据(方法一,不常用)2、定位数据&#…...
汽车电子相关术语
SOA SOA(Service-Oriented Architecture,面向服务的架构)是一种在计算机环境中设计、开发、部署和管理离散模型的方法。是由Garnter1996年提出的概念,将应用程序的不同功能单元(称为服务)进行拆分…...
Python 找出最大数
"""在输入的三个数中找出最大知识点:1、条件嵌套语句if/else2.字符串分割函数split()3、列表元素索引4、数据类型转换举一反三:1、如何控制只能输入三个数,否则重新输入2、如何避免输入无效字母"""# 定义一个变…...
Spring Security 用了那么久,你对它有整体把控吗?
文章目录 1.Servlet Filter:守门人的角色2.DelegatingFilterProxy:桥接 Servlet 和 Spring 的神器3.FilterChainProxy:Spring Security 过滤器链的管家3.SecurityFilterChain:Security 过滤器的串绳4.Spring Security 中的过滤器机…...
vue+minio实现文件上传操作
vueminio实现文件上传操作 minio文件上传vueminio实现文件上传操作 minio文件上传 minio文件上传有两种方法: 第一种是通过ak,sk,调用minio的sdk putObject进行文件上传;该方法支持go,java,js等各种语言&…...
使用JavaScript实现无限滚动的方法
前言 在网页设计中,无限滚动是一种常见的交互方式,用户可持续地加载更多内容而无需刷新页面,提高用户体验。本文将介绍如何运用JavaScript实现无限滚动的效果,使网页能够自动加载更多数据,减轻用户加载新页的负担&…...
html学习综合案例1
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>个人简介</title> </head> <body>…...
神经节苷脂抗体——博迈伦
神经节苷脂抗体是指人体免疫系统中产生的一类抗体,其主要作用是攻击神经节苷脂抗原物质。神经节苷脂是一种存在于神经细胞表面的重要分子,参与了神经细胞间的信号传导和细胞黏附等重要功能。正常情况下,人体免疫系统不会对神经节苷脂产生抗体…...
【Unity】简单的深度虚化shader
【Unity】简单的深度虚化shader 实现效果 可以用于对地图场景边界的白模处理 实现方法 1.关键方法 UnityObjectToClipPos:将物体坐标转换为屏幕坐标 LinearEyeDepth:将屏幕坐标中的z值转换为实际的深度值 saturate:将值规范到0~1之间&a…...
启动 React APP 后经历了哪些过程
本文作者为 360 奇舞团前端开发工程师 前言 本文中使用的React版本为18,在摘取代码的过程中删减了部分代码,具体以源代码为准。 在React 18里,通过ReactDOM.createRoot创建根节点。并且通过调用原型链上的render来渲染。 本文主要是从以下两个…...
带自动采集小说网站源码 小说听书网站源码 小说网站源码 带教程
PTCMS可听书可下载的小说站源码 带自动采集和搭建视频教程 必装环境:Nginx(apache.iis也可),mysql,php5.6,memcached php5.6安装扩展memcache新建站点,注意新建时,PHP版本必须选择PHP5.6 安装教程 1.上传网站文件到网站目录&…...
MySQL学习笔记2
MySQL glibc版本安装: 下载相应的安装包。 学会查看mysql的官方文档: 1) 2)点击“Reference Manual”按钮: 3)选择5.7版本: 4)点击Installing MySQL on Unix/Linux Using Generic …...
【python爬虫】—星巴克产品
文章目录 需求爬取星巴克产品以及图片,星巴克菜单 python爬虫爬取结果 需求 爬取星巴克产品以及图片,星巴克菜单 网页分析: 首先,需要分析星巴克官方网站的结构,了解菜单栏的位置、布局以及菜单项的标签或类名等信息…...
算法 矩阵最长递增路径-(递归回溯+动态规划)
牛客网: BM61 求矩阵的最长递增路径 解题思路: 1. 遍历二维矩阵每个位置,max求出所有位置分别为终点时的最长路径 2. 求某个位置为终点的最长路径时,使用动态规划dp对已经计算出的位置进行记录 3. 处理某个位置的最长路径时,如果dp[i][j]位…...
四、数学建模之图与网络模型
1.定义 2.例题及软件代码求解 一、定义 1.图和网络是相关概念 (1)图(Graph):图是数学和计算机科学中的一个抽象概念,它由一组节点(顶点)和连接这些节点的边组成。图可以是有向的&…...
php在header增加key,sign,timestamp,实现鉴权
在PHP中,您可以通过在HTTP请求的Header中增加Key、Sign和Timestamp等信息来进行安全性鉴权。 以下是一种基本的思路和示例,用于说明如何实现这种鉴权机制: 生成Key和Sign: 服务端和客户端之间共享一个密钥(Key&#x…...
Spring实例化源码解析之ConfigurationClassParser(三)
前言 上一章我们分析了ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法的源码逻辑,其中核心逻辑do while中调用parser.parse(candidates)方法,解析candidates中的候选配置类。然后本章我们主要分析ConfigurationClassParser的…...
在 Substance Painter中实现Unity Standard Shader
由于有需要在Substance Painter中显示什么样的效果,在Unity就要显示什么样的效果的需求,最近研究了几天,总算在Substance Painter中实现Unity standard的材质的渲染效果。具体效果如下: 在Unity中: Substance Painte…...
第二证券:个人开证券账户要开户费吗?
随着互联网和移动端东西的遍及,越来越多的人开端涉足股票投资,开立证券账户也成为一个热门话题。但是,许多初学者或许会有疑问,个人开证券账户是否需求支付开户费呢?这个问题的答案并不是那么简略,需求考虑…...
大厂面试-16道面试题
1 java集合类有哪些? List是有序的Collection,使用此接口能够精确的控制每个元素的插入位置,用户能根据索引访问List中元素。常用的实现List的类有LinkedList,ArrayList,Vector,Stack。 ArrayList是容量…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
