爬虫 — 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是容量…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...