当前位置: 首页 > news >正文

钉钉录播抓取视频

爬取钉钉视频

免责声明

此脚本仅供学习参考,切勿违法使用下载他人资源进行售卖,本人不但任何责任!

仓库地址:

  • 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

相关文章:

钉钉录播抓取视频

爬取钉钉视频 免责声明 此脚本仅供学习参考&#xff0c;切勿违法使用下载他人资源进行售卖&#xff0c;本人不但任何责任! 仓库地址: 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是否设置成功&#xff0c;查看版本 1.基本指令回顾 ls:list也就是列出来这个目录…...

【操作系统】——调度

&#x1f339;&#x1f60a;&#x1f339;博客主页&#xff1a;【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见&#xff1a;【C语言专项】 目录 处理机调度的概念、层次 进程调度的时机、切换与过程、方式 调度器和闲逛进程 处理机调度的概念、层…...

基于Aspose依赖添加自定义文本水印——Word、Pdf、Cell

基于Aspose依赖添加自定义文本水印——Word、Pdf、Cell 所需依赖Word水印Pdf水印——&#xff08; 注意 pdf 存在找不到字体的问题&#xff09;Excel水印 所需依赖 <dependency><groupId>com.aspose</groupId><artifactId>aspose-pdf</artifactId&g…...

【C++】—掌握STL string类:字符串操作的得力助手

#1024程序员节&#xff5c;征文# 文章目录 繁星点点映夜空&#xff0c;晨曦微露照前程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. 异常&#xff1a;程序运行过程中&#xff0c;出现的非正常情况。 2. 异常的处理&#xff1a;当异常出现时&#xff0c;执行一段预先准备好的代码。 3. 异常的处理的必要性&#xff1a;减少用户的损失、同时减小给用户带来麻烦&#xff0c;也可以对用…...

Python游戏开发超详细(基础理论知识篇)

一、引导&#xff1a; Python游戏开发是一个非常有趣且富有挑战性的领域。通过Python&#xff0c;你可以利用其强大的库和框架来创建各种类型的游戏&#xff0c;从简单的2D游戏到复杂的3D游戏。以下是第一课的基础理论知识&#xff0c;帮助你入门Python游戏开发。 二、理论知识…...

Python开发日记 -- 实现bin文件的签名

目录 1.数据的不同表现形式签名值不一样&#xff1f; 2.Binascii模块简介 3.问题定位 4.问题总结 1.数据的不同表现形式签名值不一样&#xff1f; Happy Muscle试运行了一段时间&#xff0c;组内同事再一次提出了新的需求&#xff1a;需要对bin文件签名。 PS&#xff1a;服…...

微软运用欺骗性策略大规模打击网络钓鱼活动

微软正在利用欺骗性策略来打击网络钓鱼行为者&#xff0c;方法是通过访问 Azure 生成外形逼真的蜜罐租户&#xff0c;引诱网络犯罪分子进入以收集有关他们的情报。 利用收集到的数据&#xff0c;微软可以绘制恶意基础设施地图&#xff0c;深入了解复杂的网络钓鱼操作&#xff…...

小程序无法获取头像昵称以及手机号码的深度剖析与解决方案

在当今数字化时代,小程序以其便捷、高效的特点,成为了人们生活和工作中不可或缺的一部分。然而,有时候开发者会遇到小程序无法获取头像昵称以及手机号码的问题,这给用户体验和业务流程带来了极大的困扰。本文将深入探讨这个问题的原因,并提供相应的解决方案。 一、引言 小…...

从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 中&#xff0c;resultType 和 resultMap 都用于定义从数据库查询结果到 Java 对象的映射规则&#xff0c;但它们之间存在着一些关键的区别。以下是对这两者的详细说明和区别&#xff1a; 1. resultType 定义 resultType 是 MyBatis 查询语句中的一个属性&#xf…...

文件下载漏洞

文件安全 文件下载 常见敏感信息路径 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 开发中&#xff0c;状态管理是一个至关重要的部分。随着应用的规模和复杂性增加&#xff0c;简单的局部状态管理&#xff08;如 setState() 和 InheritedWidget&#xff09;可能变得难以维护和扩展。Provider 是一种推荐的、广泛使用的 Flutter 状态管理工具&#x…...

来个Oracle一键检查

启停、切换、升级、网络改造等场景下&#xff0c;需要对数据库有些基本检查操作&#xff0c;确认当前是否运行正常&#xff0c;主打一个简单和一键搞定。 #!/bin/bash## 实例个数 告警日志 实例状态 会话 活动会话 锁 集群状态 服务状态 磁盘空间 侦听日志 ## linux vmstat 2 …...

C语言中的分支与循环(中 1)

关系操作符 C语言用于比较的表达式&#xff0c;称为"关系表达式"&#xff0c;里面使用的运算符称为关系运算符&#xff0c;关系运算符主要有以下6类。 > 大于运算符< 小于运算符>大于等于运算符< 小于等于运算符 相等运算符! 不相等运算符 下面是例子:…...

Git_GitLab

Git_GitLab 安装 服务器准备 安装包准备 编写安装脚本 初始化 GitLab 服务 启动 GitLab 服务 浏览器访问 GitLab GitLab 创建远程库 IDEA 集成 GitLab 安装 GitLab 插件 设置 GitLab 插件 安装 服务器准备 准备一个系统为 CentOS7 以上版本的服务器&#xff0c;使…...

如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

文章目录 一、什么是 Spring Boot Starter&#xff1f;二、为什么要自定义 Starter&#xff1f;三、自定义 Starter 的基本步骤1. 创建 Maven 项目2. 配置 pom.xml3. 创建自动配置类4. 创建业务逻辑类5. 创建 spring.factories 四、使用自定义 Starter五、总结推荐阅读文章 在使…...

CSS伪元素以及伪类和CSS特性

伪元素&#xff1a;可以理解为假标签。 有2个伪元素 &#xff08;1&#xff09;::before &#xff08;2&#xff09;::after ::before <!DOCTYPE html> <html> <head><title></title><style type"text/css">body::before{con…...

【论文笔记】Instantaneous Perception of Moving Objects in 3D

原文链接&#xff1a;https://arxiv.org/abs/2405.02781 简介&#xff1a;本文主张自动驾驶中细微运动的瞬时检测和量化与一般的大型运动同等重要。具体来说&#xff0c;由于激光雷达点云缺乏帧间对应关系&#xff0c;静态物体可能看起来在运动&#xff08;称为游泳效应&#x…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...

绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化

iOS 应用的发布流程一直是开发链路中最“苹果味”的环节&#xff1a;强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说&#xff0c;这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发&#xff08;例如 Flutter、React Na…...