钉钉录播抓取视频
爬取钉钉视频
免责声明
此脚本仅供学习参考,切勿违法使用下载他人资源进行售卖,本人不但任何责任!
仓库地址:
- GItee 源码仓库
执行顺序
- poxyM3u8开启代理
- getM3u8url用于获取m3u8文件
- userAgent随机请求头
- downVideo|downVideoThreadTqdm单线程下载和多线程下载,二选一即可
启动顺序:poxyM3u8开启代理 -> getM3u8url获取文件->downVideo遍历文件进行下载
像这样别人给的钉钉链接我想要它的视频, 但是又没有下载按钮,我该怎么办呢?

我想到了用爬虫爬取
方案一
检查了一下网络请求发现它是采用m3u8文件格式保存的,所以找m3u8的文件。找到了

-
对它写代码进行保存:
with open("4f8122f4-f8fb-43d5-b8c8-7c1c9a4a70f7_normal.m3u8", "r", encoding="utf-8") as f:centen = f.read() print(centen) pattern = r'([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\/[\d]+\.ts\?auth_key=[\d\w-]+)' matches = re.findall(pattern, centen) print(matches) # urls = [] for match in matches:url = "https://dtliving-bj.dingtalk.com/live_hp/" + matchurls.append(url) # print(len(urls)) # for i in urls: # print(i)for item in tqdm(urls,disable="下载"):response = requests.get(item)with open("E:/a.mp4", "ab", ) as f:f.write(response.content)下载是下载下来了, 可是我有很多很多集,我自己下载是不是太麻烦了,也累。所以我就分析了一下这个地址
发现:
m3u8:https://dtliving-sz.dingtalk.com/live_hp/8618428f-dc2e-419e-bc6b-b93a6ee6b28c_normal.m3u8?auth_key=1730544823-fb9347e4a68a456b8b265afa36700f15-0-f24f0b45c72dd6547dadf77466f68ce4url:https://n.dingtalk.com/dingding/live-room/index.html?roomId=ZxaInSr3io8j9iZf&liveUuid=8618428f-dc2e-419e-bc6b-b93a6ee6b28c8618428f-dc2e-419e-bc6b-b93a6ee6b28c_normal.m3u8,其中8618428f-dc2e-419e-bc6b-b93a6ee6b28c是Uuid既然:
8618428f-dc2e-419e-bc6b-b93a6ee6b28c是房间号的话那我把好多集的房间号爬下来然后拼接到dtliving-sz.dingtalk.com/live_hp/房间号_normal.m3u8这样不就行了?然后拼接好我就发了一个请求发现并不能下载下来

原因是`auth_key`的原因, 然后我尝试寻找`auth_key`

emmm, 找了许久,打扰了。还是能力不够, 所以打算换一个方式。
方案二
我发现浏览器是可以获取到auth_key的那我不如我去拿浏览器的响应值。
相当于做了一件中间人的方式把我想要的东西抓取出来。
我使用了mitmproxy当我的代理
pip install mitmproxy
然后写一段代码来捕捉我想要抓取的url的响应
from mitmproxy import ctx,http
# http://mitm.it/ 证书
# mitmdump.exe -s .\test5.py
# mitmweb
import re
import requestsdef request(flow):# 获取请求对象request = flow.request# 实例化输出类math = re.match("^(.*?)_normal.m3u8", request.url)if math:info = ctx.log.info# 打印请求的urlinfo("请求地址: " + request.url + "\n")string = request.urlstart_index = string.find("auth_key=") + len("auth_key=")end_index = len(string)result = string[start_index:end_index]print(result)info("请求体: " + request.text + "\n")# # 打印请求方法info("请求方法: " + request.method)def response(flow):m3u8math = re.match("^(.*?)_normal.m3u8", flow.request.url)if m3u8math:print("===============这是m3u8格式的文件响应============================")centen = flow.response.get_text()with open("./m3u8s/{0}.m3u8".format(title), "w") as f:f.write(centen)print("===============结束============================")
代码写好了,然后打开本机代理改成mitmproxy的代理然后安装证书,之后就可以愉快的抓请求了
1、代码启动

2、代理设置:

3、证书安装:
- 设置好系统代理后,浏览器输入
http://mitm.it/, 然后选择对应系统的证书安装就行。

4、抓取
- 当我使用浏览器打开
https://n.dingtalk.com/dingding/live-room/index.html?roomId=AAToXdFAVGArvaQx&liveUuid=9aac3549-698f-46b9-9bb0-f2f44d4faaca的时候它就会帮我把特定m3u8的请求响应做文件保存
from mitmproxy import ctx,http
# http://mitm.it/ 证书
# mitmdump.exe -s .\xiaoyuan.py
# mitmweb
import re
import requests
def response(flow):titlesearch = re.search(r"roomId=(.*?)&liveUuid=(.*)", flow.request.url)if titlesearch:global roomIdAndUidroomIdAndUid = titlesearchcentent = flow.response.get_content().decode('utf-8')titleRe = re.search(r'<meta property="og:title" content="(.*?)">',centent)global titletitle = titleRe.group(1)print(title)else:m3u8math = re.match(r"^(.*)/(.*?)_normal.m3u8", flow.request.url)if m3u8math:print("===============这是m3u8格式的文件响应============================")print("房间号:", roomIdAndUid.group(2), "========", roomIdAndUid.group(1))centen = flow.response.get_text()try:with open("./杰哥数学m3u8/{0}.m3u8".format(title), "w") as f:f.write(centen)except OSError:with open("./log.txt".format(title), "a") as f:f.write("标题: {0}, roomId:{1}, UuId: {2}, url:https://n.dingtalk.com/dingding/live-room/index.html?roomId={3}&liveUuid={4}\n".format(title,roomIdAndUid.group(1),roomIdAndUid.group(2),roomIdAndUid.group(1),roomIdAndUid.group(2),))print("===============结束============================")

可是我有很多个链接

所以我打算使用webdriver帮我做批量的链接请求, 而且这个必须要登录才能播放而webdriver会打断我的登录状态,为了保存我的登录状态所以我直接调试本机的chrome。
1、关闭chrome浏览器
2、终端输入
chrome.exe --remote-debugging-port=9222
3、确认是登录状态后,执行代码
import time
from selenium import webdriver
from selenium import webdriveroptions = webdriver.ChromeOptions()
options.set_headless()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome("chromedriver-win64/chromedriver-win64/chromedriver.exe",chrome_options=options)
driver.get('https://n.dingtalk.com/dingding/live-room/index.html?roomId=AAToXdFAVGArvaQx&liveUuid=9aac3549-698f-46b9-9bb0-f2f44d4faaca')
这段代码一执行马上就把这个m3u8文件下载下来了

接下来执行多个url把他们m3u8都下载下来,我只需要把它们都打开然后进行代理检测到就会帮我们下载m3u8文件
import timefrom selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as ECoptions = webdriver.ChromeOptions()
options.set_headless()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome("chromedriver-win64/chromedriver-win64/chromedriver.exe",chrome_options=options)
driver.implicitly_wait(10)def newTable(urls, i):if len(urls) > i:window_handles = driver.window_handles# 切换到新标签页print(window_handles)new_tab = window_handles[-1]driver.switch_to.window(new_tab)driver.get(urls[i])login_btn = WebDriverWait(driver, 10, 0.5).until(EC.visibility_of_element_located((By.ID, "live-room")))if login_btn:time.sleep(5)i += 1print(i)newTable(urls, i)with open("钉钉1.txt", "r", encoding="utf-8") as f:urls = f.readlines()driver.get(urls[0])time.sleep(5)newTable(urls, 1)
然后再对m3u8文件进行遍历下载
import re
import requests
import os
import tqdm
requests.packages.urllib3.disable_warnings()with open("m3u8/af941a57-92ad-487f-a2a1-a4682f07afc4_normal.m3u8", "r", encoding="utf-8") as file:content = file.read()# fileName = os.path.basename(file_path).split(".")[0]
# print(f"文件 {os.path.basename(file_path)} 的内容为:{content}")
pattern = r'([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\/[\d]+\.ts\?auth_key=[\d\w-]+)'
matches = re.findall(pattern, content)m3u8Url = ["https://dtliving-sz.dingtalk.com/live_hp/", "https://dtliving-sh.dingtalk.com/live_hp/"]def getStatusUrl():for status in m3u8Url:url = status + matches[0]responseStatus = requests.get(url, verify=False)print(status, responseStatus.status_code)if responseStatus.status_code == 200:return status
def getMp4Url():urls = []status = getStatusUrl()for match in matches:url = status+matchurls.append(url)return urlsdef run():urls = getMp4Url()for item in tqdm.tqdm(urls):response = requests.get(item, verify=False)if response.status_code == 200:# with open("/disk/data/杰哥数学/{0}.mp4".format("习题课1"), "ab", ) as f:with open(r"E:\杰哥数学\{0}.mp4".format("习题课1"), "ab", ) as f:f.write(response.content)run()
这样就可以下载文件了
总结
流程分析
由于解密困难,所以采用mitmproxy进行代理实现直接抓取视频需要请求的m3u8格式的文件,然后进行保存
- 启动代理
- 模拟浏览器访问视频地址
- 下载所有m3u8的文件
- 对m3u8文件进行清洗
- 拼装ts片段视频的地址
- 保存视频
完整代码
1、启动代理
poxyM3u8.py
from mitmproxy import ctx,http
# http://mitm.it/ 证书
# mitmdump.exe -s .\xiaoyuan.py
# mitmweb
import re
import requestsdef setM3u8Status():"""1 表示下载好了 """with open("m3u8Status.txt", "w") as f:f.write("0")def response(flow):titlesearch = re.search(r"roomId=(.*?)&liveUuid=(.*)", flow.request.url)if titlesearch:global roomIdAndUidroomIdAndUid = titlesearchcentent = flow.response.get_content().decode('utf-8')titleRe = re.search(r'<meta property="og:title" content="(.*?)">',centent)global titletitle = titleRe.group(1)print(title)else:m3u8math = re.match(r"^(.*)/(.*?)_normal.m3u8", flow.request.url)if m3u8math:print("===============这是m3u8格式的文件响应============================")print("房间号:", roomIdAndUid.group(2), "========", roomIdAndUid.group(1))centen = flow.response.get_text()try:with open(r"./m3u8/{0}.m3u8".format(title.replace("/", "-")).replace("\t", " "), "w") as f:f.write(centen)setM3u8Status()except OSError as e:print("==================================错误====================================")print(e)print("==================================错误====================================")with open("./log.txt".format(title), "a") as f:f.write("标题: {0}, roomId:{1}, UuId: {2}, url:https://n.dingtalk.com/dingding/live-room/index.html?roomId={3}&liveUuid={4}\n".format(title,roomIdAndUid.group(1),roomIdAndUid.group(2),roomIdAndUid.group(1),roomIdAndUid.group(2),))print("===============结束============================")
2、模拟浏览器进行请求
getM3u8.py
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as ECoptions = webdriver.ChromeOptions()
options.set_headless()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome("../chromedriver-win64/chromedriver-win64/chromedriver.exe", chrome_options=options)
driver.implicitly_wait(10)def newTable(urls, i):if len(urls) > i:window_handles = driver.window_handles# 切换到新标签页print(window_handles)new_tab = window_handles[-1]driver.switch_to.window(new_tab)setM3u8Status()driver.get(urls[i])while getM3u8FileStatus():time.sleep(5)i += 1print(i)newTable(urls, i)# login_btn = WebDriverWait(driver, 10, 0.5).until(EC.visibility_of_element_located((By.ID, "live-room")))# if login_btn:# time.sleep(5)# i += 1# print(i)# newTable(urls, i)def getM3u8FileStatus():with open("m3u8Status.txt", "r", encoding="utf-8") as f:status = f.read()time.sleep(2)return "1" == statusdef setM3u8Status():"""0 表示新的请求等待 """with open("m3u8Status.txt", "w") as f:f.write("1")time.sleep(2)with open("钉钉1.txt", "r", encoding="utf-8") as f:urls = f.readlines()driver.get(urls[0])while getM3u8FileStatus():time.sleep(5)newTable(urls, 1)
3、最后下载文件
我发现m3u8里面的ts请求不止一个域名
有两个,用错了域名会报404状态码
m3u8Url = ["https://dtliving-sz.dingtalk.com/live_hp/", "https://dtliving-sh.dingtalk.com/live_hp/"]
userAgent 随机请求头
import random
import stringbrowsers = ["Chrome", "Firefox", "Safari", "Edge", "Opera"]
operating_systems = ["Windows NT", "Macintosh", "Linux", "iPhone", "iPad", "Android"]
versions = [str(i) for i in range(80, 130)]def generate_random_string(length):return ''.join(random.choices(string.ascii_letters + string.digits, k=length))def generate_user_agents(num):user_agents = []for _ in range(num):browser = random.choice(browsers)os = random.choice(operating_systems)version = random.choice(versions)if os == "Windows NT":ua = f"Mozilla/5.0 ({os}; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) {browser}/{version} Safari/537.36"elif os == "Macintosh":ua = f"Mozilla/5.0 ({os}; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) {browser}/{version} Safari/537.36"elif os == "Linux":ua = f"Mozilla/5.0 ({os}; x86_64) AppleWebKit/537.36 (KHTML, like Gecko) {browser}/{version} Safari/537.36"elif os == "iPhone":ua = f"Mozilla/5.0 (iPhone; CPU iPhone OS {generate_random_string(2)}_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/{version} Mobile/15E148 Safari/604.1"elif os == "iPad":ua = f"Mozilla/5.0 (iPad; CPU OS {generate_random_string(2)}_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/{version} Mobile/15E148 Safari/604.1"elif os == "Android":ua = f"Mozilla/5.0 (Linux; Android {generate_random_string(2)}; {generate_random_string(10)}) AppleWebKit/537.36 (KHTML, like Gecko) {browser}/{version} Mobile Safari/537.36"user_agents.append(ua)return user_agents# print(random.choice(generate_user_agents(100)))
downVideo.py
import os
import random
import time
import requests
import re
from tqdm import tqdm
requests.packages.urllib3.disable_warnings()
import glob
from userAgent import generate_user_agentsheaders = {'User-Agent': random.choice(generate_user_agents(100))}
folder_path = 'm3u8'
# 获取文件列表并添加进度条
file_paths = list(tqdm(glob.glob(folder_path + '/**/*', recursive=True), desc="获取文件列表进度"))m3u8Url = ["https://dtliving-sz.dingtalk.com/live_hp/", "https://dtliving-sh.dingtalk.com/live_hp/", "https://dtliving-bj.dingtalk.com/live_hp/"]def getStatusUrl(fileName, m3u8, i):url = m3u8Url[i] + m3u8print(f"第{i}次,正在检测{url}....")response = requests.get(url, headers=headers, verify=False)if response.status_code == 200:print(f"域名检测成功{m3u8}的域名是{m3u8Url[i]}")return m3u8Url[i]else:i+=1if len(m3u8Url) > i:print(f"第{i},次检测{url}....")getStatusUrl(fileName, m3u8, i)else:print(f"错误")with open("./errorUrl.txt", "a", encoding="utf-8") as f:f.write(f"{m3u8}没有找到合适的域名, 文件名称是: {fileName}")def getMp4Url(matches,fileName, m3u8, i):urls = []status = getStatusUrl(fileName, m3u8, i)for match in matches:url = status+matchurls.append(url)return urlsfor file_path in file_paths:if os.path.isfile(file_path):with open(file_path, 'r', encoding="utf-8") as file:content = file.read()fileName = os.path.basename(file_path).split(".")[0]# print(f"文件 {os.path.basename(file_path)} 的内容为:{content}")pattern = r'([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\/[\d]+\.ts\?auth_key=[\d\w-]+)'matches = re.findall(pattern, content)urls = getMp4Url(matches, fileName, matches[0], 0)# 处理每个文件中的链接列表并添加进度条for item in tqdm(urls, desc=f"处理 {fileName} 文件内链接进度"):response = requests.get(item, verify=False)time.sleep(2)# with open("/disk/data/杰哥数学/{0}.mp4".format(fileName), "ab", ) as f:with open(r"E:\杰哥数学\{0}.mp4".format(fileName), "ab", ) as f:f.write(response.content)
也可以是多线程这样下载更快
import os
import random
import time
import requests
import re
from tqdm import tqdm
import glob
from userAgent import generate_user_agents
import threadingrequests.packages.urllib3.disable_warnings()# 设置请求头
headers = {'User-Agent': random.choice(generate_user_agents(100))}# 设置文件夹路径
folder_path = 'm3u8'# 获取文件列表并添加进度条
file_paths = list(tqdm(glob.glob(folder_path + '/**/*', recursive=True), desc="获取文件列表进度"))# 定义m3u8的URL列表
m3u8Url = ["https://dtliving-sz.dingtalk.com/live_hp/", "https://dtliving-sh.dingtalk.com/live_hp/", "https://dtliving-bj.dingtalk.com/live_hp/"]def getStatusUrl(fileName, m3u8, i):url = m3u8Url[i] + m3u8print(f"第{i}次,正在检测{url}....")log.write(f"第{i}次,正在检测{url}....")response = requests.get(url, headers=headers, verify=False)if response.status_code == 200:print(f"域名检测成功{m3u8}的域名是{m3u8Url[i]}")log.write(f"域名检测成功{m3u8}的域名是{m3u8Url[i]}")return m3u8Url[i]else:i += 1if len(m3u8Url) > i:print(f"第{i},次检测{url}....")log.write(f"第{i},次检测{url}....")return getStatusUrl(fileName, m3u8, i)else:log.write(f"第{i},{url}域名匹配失败....")with open("./errorUrl.txt", "a", encoding="utf-8") as f:f.write(f"{m3u8}没有找到合适的域名, 文件名称是: {fileName}")def getMp4Url(matches, fileName, m3u8, i):urls = []status = getStatusUrl(fileName, m3u8, i)for match in matches:url = status+matchurls.append(url)return urlsdef process_file(file_path):global loglog = open("log.txt", "a", encoding="utf-8")if os.path.isfile(file_path):with open(file_path, 'r', encoding="utf-8") as file:content = file.read()fileName = os.path.basename(file_path).split(".")[0]pattern = r'([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\/[\d]+\.ts\?auth_key=[\d\w-]+)'matches = re.findall(pattern, content)urls = getMp4Url(matches, fileName, matches[0], 0)# 处理每个文件中的链接列表并添加进度条for item in tqdm(urls, desc=f"处理 {fileName} 文件内链接进度"):response = requests.get(item, verify=False)time.sleep(2)# with open(r"E:\杰哥数学\{0}.mp4".format(fileName), "ab", ) as f:with open("/disk/data/杰哥数学/{0}.mp4".format(fileName), "ab", ) as f:f.write(response.content)log.close()# 创建线程列表
threads = []# 遍历文件路径列表,为每个文件创建一个线程进行处理
for file_path in file_paths:thread = threading.Thread(target=process_file, args=(file_path,))threads.append(thread)thread.start()# 等待所有线程完成
for thread in threads:thread.join()
效果

注意事项
- 不要忘记开系统代理
- chrome浏览器需要全部关闭才可以
chrome.exe --remote-debugging-port=9222这个命令,不然selenium会没反应 - 不要忘记安装证书
- 要是下载请求失败的话,请注意访问的频率、更换请求头和IP
相关文章:
钉钉录播抓取视频
爬取钉钉视频 免责声明 此脚本仅供学习参考,切勿违法使用下载他人资源进行售卖,本人不但任何责任! 仓库地址: GItee 源码仓库 执行顺序 poxyM3u8开启代理getM3u8url用于获取m3u8文件userAgent随机请求头downVideo|downVideoThreadTqdm单线程下载和…...
centos下面的jdk17的安装配置
文章目录 1.基本指令回顾2.jdk17的安装到这个centos上面2.1首先切换到这个root下面去2.2查看系统jdk版本2.3首先到官网找到进行下载2.4安装包的上传2.5jdk17的安装包的解压过程2.6配置环境变量2.7是否设置成功,查看版本 1.基本指令回顾 ls:list也就是列出来这个目录…...
【操作系统】——调度
🌹😊🌹博客主页:【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见:【C语言专项】 目录 处理机调度的概念、层次 进程调度的时机、切换与过程、方式 调度器和闲逛进程 处理机调度的概念、层…...
基于Aspose依赖添加自定义文本水印——Word、Pdf、Cell
基于Aspose依赖添加自定义文本水印——Word、Pdf、Cell 所需依赖Word水印Pdf水印——( 注意 pdf 存在找不到字体的问题)Excel水印 所需依赖 <dependency><groupId>com.aspose</groupId><artifactId>aspose-pdf</artifactId&g…...
【C++】—掌握STL string类:字符串操作的得力助手
#1024程序员节|征文# 文章目录 繁星点点映夜空,晨曦微露照前程1.string的基本概念2.标准库中的string类2.1 string类2.2 auto和范围for2.3 string类常用的接口2.4 string类对象的容量操作2.5 string类对象的访问及遍历操作2.6 string类对象的修改操作2…...
【Java笔记】第十四章:异常
一、概念【理解即可】 1. 异常:程序运行过程中,出现的非正常情况。 2. 异常的处理:当异常出现时,执行一段预先准备好的代码。 3. 异常的处理的必要性:减少用户的损失、同时减小给用户带来麻烦,也可以对用…...
Python游戏开发超详细(基础理论知识篇)
一、引导: Python游戏开发是一个非常有趣且富有挑战性的领域。通过Python,你可以利用其强大的库和框架来创建各种类型的游戏,从简单的2D游戏到复杂的3D游戏。以下是第一课的基础理论知识,帮助你入门Python游戏开发。 二、理论知识…...
Python开发日记 -- 实现bin文件的签名
目录 1.数据的不同表现形式签名值不一样? 2.Binascii模块简介 3.问题定位 4.问题总结 1.数据的不同表现形式签名值不一样? Happy Muscle试运行了一段时间,组内同事再一次提出了新的需求:需要对bin文件签名。 PS:服…...
微软运用欺骗性策略大规模打击网络钓鱼活动
微软正在利用欺骗性策略来打击网络钓鱼行为者,方法是通过访问 Azure 生成外形逼真的蜜罐租户,引诱网络犯罪分子进入以收集有关他们的情报。 利用收集到的数据,微软可以绘制恶意基础设施地图,深入了解复杂的网络钓鱼操作ÿ…...
小程序无法获取头像昵称以及手机号码的深度剖析与解决方案
在当今数字化时代,小程序以其便捷、高效的特点,成为了人们生活和工作中不可或缺的一部分。然而,有时候开发者会遇到小程序无法获取头像昵称以及手机号码的问题,这给用户体验和业务流程带来了极大的困扰。本文将深入探讨这个问题的原因,并提供相应的解决方案。 一、引言 小…...
从0到1,搭建vue3项目
一 Vite创建Vue3项目 1.1.创建Vue3项目 1.1.1.运行创建项目命令 # 使用 npm npm create vitelatest 1.1.2、填写项目名称 1.1.3、选择前端框架 1.1.4、选择语法类型 1.1.5、按提示运行代码 1.1.6浏览器问 localhost:5173 预览 1.2项目结构 1.2.1vite.config.ts 1.2.2 pac…...
Mybatis mapper文件 resultType和resultMap的区别
在 MyBatis 中,resultType 和 resultMap 都用于定义从数据库查询结果到 Java 对象的映射规则,但它们之间存在着一些关键的区别。以下是对这两者的详细说明和区别: 1. resultType 定义 resultType 是 MyBatis 查询语句中的一个属性…...
文件下载漏洞
文件安全 文件下载 常见敏感信息路径 Windows C:\boot.ini //查看系统版本 C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件 C:\Windows\repair\sam //存储系统初次安装的密码 C:\Program Files\mysql\my.ini //Mysql配置 C:\Program Files\mysql\data\mysql\user.…...
【Flutter】状态管理:Provider状态管理
在 Flutter 开发中,状态管理是一个至关重要的部分。随着应用的规模和复杂性增加,简单的局部状态管理(如 setState() 和 InheritedWidget)可能变得难以维护和扩展。Provider 是一种推荐的、广泛使用的 Flutter 状态管理工具&#x…...
来个Oracle一键检查
启停、切换、升级、网络改造等场景下,需要对数据库有些基本检查操作,确认当前是否运行正常,主打一个简单和一键搞定。 #!/bin/bash## 实例个数 告警日志 实例状态 会话 活动会话 锁 集群状态 服务状态 磁盘空间 侦听日志 ## linux vmstat 2 …...
C语言中的分支与循环(中 1)
关系操作符 C语言用于比较的表达式,称为"关系表达式",里面使用的运算符称为关系运算符,关系运算符主要有以下6类。 > 大于运算符< 小于运算符>大于等于运算符< 小于等于运算符 相等运算符! 不相等运算符 下面是例子:…...
Git_GitLab
Git_GitLab 安装 服务器准备 安装包准备 编写安装脚本 初始化 GitLab 服务 启动 GitLab 服务 浏览器访问 GitLab GitLab 创建远程库 IDEA 集成 GitLab 安装 GitLab 插件 设置 GitLab 插件 安装 服务器准备 准备一个系统为 CentOS7 以上版本的服务器,使…...
如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
文章目录 一、什么是 Spring Boot Starter?二、为什么要自定义 Starter?三、自定义 Starter 的基本步骤1. 创建 Maven 项目2. 配置 pom.xml3. 创建自动配置类4. 创建业务逻辑类5. 创建 spring.factories 四、使用自定义 Starter五、总结推荐阅读文章 在使…...
CSS伪元素以及伪类和CSS特性
伪元素:可以理解为假标签。 有2个伪元素 (1)::before (2)::after ::before <!DOCTYPE html> <html> <head><title></title><style type"text/css">body::before{con…...
【论文笔记】Instantaneous Perception of Moving Objects in 3D
原文链接:https://arxiv.org/abs/2405.02781 简介:本文主张自动驾驶中细微运动的瞬时检测和量化与一般的大型运动同等重要。具体来说,由于激光雷达点云缺乏帧间对应关系,静态物体可能看起来在运动(称为游泳效应&#x…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
