Pyppeteer 的使用

puppeteer 是基于Node.js  开发的一个工具,  有了它,我们可以利用 JavaScript 控制 Chrome 浏览器的一些操作。当然, puppeteer 也可以用于网络爬虫,其 API 及其完善,功能非常强大。

Pyppeteer 其实是 puppeteer 的 python 实现, 但不是 google 开发的,是由以为来自日本的工程师根据 puppeteer 的一些功能开发出来的非官方版本。

pyppeteer 的背后实际上有一个类似于 Chrome 的浏览器---Chromium, 它执行一些动作,从而进行网页渲染,首先,介绍一下 Chromium 浏览器和 Chrome 浏览器的渊源。

Chromium是Google 为了研发 Chrome启动的项目, 是完全开源的。 二者基于相同的源代码而构建, CHrome 的所有新功能都会先在 Chromium 上实现,待验证稳定后才移植在 Chrome 上, 因此Chromium 的版本更新频率更高, 同时也包含很多新功能。 但作为一款独立的浏览器,Chromium的用户群体要小的多。两款浏览器同根同源,有着同样的 logo ,只是配色不同

总得说,两款浏览器内核一样, 实现方式一样,可以看做开发板和正式版,功能上没有太大区别

pyppeteer 就是依赖 Chromium 浏览器运行的,如果第一次运行 pyppeteer 的时候,没有 安装Chromium 浏览器,程序就会帮我们自动安装和配置好, 免去了繁琐的环境配置等工作。 另外, pyppeteer 是基于 python 新特性 async 实现的,所以它的一些操作执行也支持异步

安装

pip install pyppeteer

快速上手

一个带有 Ajax 接口 还有加密参数的网站,没办法用 requests 直接爬取,但可以用 selenium 爬取,这里使用 pyppeteer 爬取

import asyncio
from pyppeteer import launch
from pyquery import PyQuery as pqasync def main():browser = await launch()page = await browser.newPage()await page.goto('https://spa2.scrape.center/')await page.waitForSelector('.item .name')doc = pq(await page.content())names = [item.text() for item in doc('.item .name').items()]print('Names:', names)await browser.close()asyncio.get_event_loop().run_until_complete(main())

如果是第一次运行可能会报错:

Starting Chromium download

原因是: 下载 Chromium 慢或者下载失败

解决方法:

1. 进入网址

CNPM Binaries Mirror

选择对应自己系统的文件

选一个最近或者自己需要的日期版本 

右键复制链接,不要下载

然后找到自己的python环境中的site-packages中pyppeteer中的chromium_downloader.py文件并打开

chromium_downloader.py 的位置,一般在报错的信息里面可以找到

我的位置:C:\Users\86151\AppData\Roaming\Python\Python311\site-packages\pyppeteer

右键选择打开方式,记事本或者别的什么。

将刚才复制的链接粘贴上去,保存,重新运行上面的代码 OK

Names: ['霸王别姬 - Farewell My Concubine', '这个杀手不太冷 - Léon', '肖申克的救赎 - The Shawshank Redemption', '泰坦尼克号 - Titanic', '罗马假日 - Roman Holiday', '唐伯虎点秋香 - Flirting Scholar', '乱世佳人 - Gone with the Wind', '喜剧之王 - The King of Comedy', '楚门的世界 - The Truman Show', '狮子王 - The Lion King']
 

这里我们访问了测试网站, 然后等待 .item .name 节点加载出来,随后通过 pyquery 从页面远吗中提取电影名称并输出,最后关闭 Pyppeteer 。 如上面所示,我们成功模拟了页面的加载行为,然后成功提取了上面所有的电影名称

逐行分析:

调用 launch 方法新建了一个 Browser 对选哪个, 并赋值给 browser 变量,这一步相当于启动了浏览器,前面如果报错,就会指向这里

调用了 browser 的 newPage 方法, 新建了一个Page 对象, 并赋值给 page 变量。相当于在浏览器中新建了一个选项卡,这是后虽然启动了一个选项卡,但是还未访问任何页面,浏览器依然是空白的

调用了 page 的 goto 方法相当于在浏览器地址栏中输入了 goto 方法参数中的 URL , 之后浏览器加载对应的页面

调用了 page 的 waitForSelector 方法,传入选择器,页面就会等待选择器对应节点的信息加载出来, 加载出来后, 就立即返回, 否则继续等待直到超时。如果顺利的话,页面会成功加载出来

页面加载完成之后,调用 content 方法,可以获取当前浏览器页面的源代码,这就是 JavaScript 渲染后的结果

进一步, 用 pyquery 解析并提取页面上的电影名称,就得到最终结果了

其中的 async  await 是关于异步的方法

再看一个例子:

import asyncio
from pyppeteer import launchwidth, height = 1366, 768async def main():browser = await launch()page = await browser.newPage()await page.setViewport({'width': width, 'height': height})await page.goto('https://spa2.scrape.center/')await page.waitForSelector('.item .name')await asyncio.sleep(2)await page.screenshot({'path': 'screen.png'})dimensions = await page.evaluate("""() => {return {width: document.documentElement.clientWidth,height: document.documentElement.clientHeight,deviceScaleFactor: window.devicePixelRatio,}}""")print(dimensions)await browser.close()
asyncio.get_event_loop().run_until_complete(main())

{'width': 1366, 'height': 768, 'deviceScaleFactor': 1}

这里我们用到了几个新方法, 设置了页面窗口大小,保存了页面截图, 执行 JavaScript 语句并返回了对应的数据。 其中,再 screenshot 方法里, 通过path 参数传入页面截图的保存路径,另外还可指定截图的保存格式 type, 清晰度 quality , 是否全屏 fullPage 和裁切 clip 等参数

截图如下

可以看到,返回结果是 JavaScript 渲染之后的页面,和我们在浏览器中看到的一样。

我们还调用了 evaluate 方法执行了一些 JavaScript 语句, 这里给 JavaScript 传入了一个函数, 使用 return 方法返回了页面的 宽 ,高 像素大小比率这三个值, 最后得到的是一个 JSON 格式的对象, 内容如下

{'width': 1366, 'height': 768, 'deviceScaleFactor': 1}

官方文档: https://pyppeteer.github.io/pyppeteer/reference.html

说明: 上面代码运行的时候可能报错:

出现这个错误,只要把这里面的

return {width: document.documentElement.clientWidth,height: document.documentElement.clientHeight,deviceScaleFactor: window.devicePixelRatio,
}

deviceScaleFactor: window.devicePixelRatio,

删掉就好了,具体原因暂时不知道,反正时好时坏的

launch 方法

launch 方法相当于在桌面上点击浏览器图标,打开浏览器

文档链接: https://pyppeteer.github.io/pyppeteer/reference.html#launcher

方法定义:

pyppeteer.launcher.launch(options:dict=None, **kwargs) -> pyppeteer.browser.Browser

可以看出,launch 方法处于 launcher 模块中, 在声明中没有 特别指定的参数,返回值是 browser 模块中的 Browser 对象, 另外源码可以发现, 这是一个  async 修饰的对象,所以在调用的时候需要使用 await 

接下来看看 launch 的参数

ignoreHTTPSErrors (bool) :是否忽略 HTTPS 的错误,默认 False

headless (bool) :是否启用无头模式, 即无界面模式,如果 devtools  参数是 True , 该参数就会被设置为 False , 否则为 True , 即默认开启无界面模式

executablePath (str) : 可执行文件的路径。 指定该参数后就不需要使用默认的 Chromium 浏览器了,可以指定已有的 Chrome 或者 Chromiun

slowMo (int | float) : 通过传入指定的时间,可以减缓 Pyppeteer 的一些模拟操作

args (List | [str] ) : 在执行过程中传入的额外参数

ignoreDefaultArgs (bool) :是否忽略 Pyppeteer 的默认参数。 如果使用这个参数,那么最好通过 args 设置一些参数, 否则可能会出现一些意想不到的问题。 这个参数相对比较危险,慎用

handleSIGINT (bool) : 是否响应 SIGINT 信号,也就是是否可以使用 Ctrl + C 终止浏览器程序,默认是 True

handleSIGTERM (bool) :  是否响应 SIGTERM 信号(一般是 kill 命令), 默认是 True

handleSIGHUP (bool) : 是否响应 SIGHUP 信号, 即挂起信号, 例如终端退出操作, 默认是 True

dumpio (bool) : 是否将 Pyppeteer 的输出内容传递给 process.stdout 对象和 process.stderr 对象,默认是 False 

userDataDir (str) : 用户数据文件夹, 可以保留一些个性化配置和操作记录

env (dict) ; 环境变量, 可以传入字典形式的数据

devtools (bool) : 是否自动为每一页开启调试工具, 默认是 False .如果将这个参数设置为 True , 那么 headless 参数就会无效, 会被强制设置为 False

logLevel (int | str) :日志级别,默认和 root logger 对象级别相同

autoClose (bool) : 当一些命令执行完后, 是否自动关闭浏览器,默认是 True

loop (asyncio.AbstractEventLoop) : 时间循环对象

下面来稍微使用一下这些参数:

无头模式

一般在生产环境中都是默认为 True 这里来设置为 False 试一下

import asyncio
from pyppeteer import launchasync def main():await launch(headless=False)await asyncio.sleep(100)asyncio.get_event_loop().run_until_complete(main())

一个空的浏览器,可以自己看一下版本和相关信息

调试模式

在写爬虫的时候经常需要分析网页结构和网络请求,所以开启调试模式还是很有必要的

直接将 devtools 设置为 True 即可

import asyncio
from pyppeteer import launchasync def main():browser = await launch(devtools=True)page = await browser.newPage()await page.goto('https://baidu.com')await asyncio.sleep(30)asyncio.run(main())

当我们开启调试模式时, 就会默认关闭无头模式

禁用提示条

每次打开浏览器都能看到

现在来关闭它,需要设置 args 参数

import asyncio
from pyppeteer import launchasync def main():browser = await launch(headless=False, args=['--disable-infobars'])page = await browser.newPage()await page.goto('https://antispider1.scrape.center/')await asyncio.sleep(30)asyncio.run(main())

并没有用,提示条还在

防止检测

查看被检测到的状态

import asyncio
from pyppeteer import launchasync def main():browser = await launch(headless=False, args=['--disable-infobars'])page = await browser.newPage()await page.goto('https://antispider1.scrape.center/')await asyncio.sleep(30)asyncio.run(main())

用上面的代码访问,发现并不能展示内容

Pyppeteer 的 Page 对象有一个叫作 evaluateOnNewDocument 的方法, 意思是每次加载的时候执行某条语句,这里可以利用它来执行隐藏 Webdriver 属性的命令

import asyncio
from pyppeteer import launch#防止检测
async def main():browser = await launch(headless=False, args=['--disable-infobars'])page = await browser.newPage()await page.evaluateOnNewDocument('Object.defineProperty(navigator, "webdriver", {get: () => undefined})')await page.goto('https://antispider1.scrape.center/')await asyncio.sleep(30)asyncio.run(main())

页面加载出来了

页面大小设置

根据情况使用, 调用 page 对象的  setViewporet 方法即可

import asyncio
from pyppeteer import launchwidth,height = 1366, 768async def main():browser = await launch(headless=False, args=['--disable-infobars', f'--window-size={width},{height}'])page = await browser.newPage()await page.setViewport({'width': width, 'height': height})await page.evaluateOnNewDocument('Object.defineProperty(navigator, "webdriver", {get: () => undefined})')await page.goto('https://antispider1.scrape.center/')await asyncio.sleep(30)asyncio.run(main())

可以看到窗口的大小改变了

用户数据持久化

问题: 每次打开浏览器的时候都是一个新的浏览器,并没有保存任何之前的信息,例如用户登陆。在淘宝我们登陆之后,就算这次退出,下次打开依旧保持登录状态,这就是因为,一些用户的基本信息在本地保存着,下次打开时,读取了本地信息,所以能保持登录状态。

设置用户目录,在启动浏览器的时候 设置 userDataDir 属性

import asyncio
from pyppeteer import launchasync def main():browser = await launch(headless=False, userDataDir='./userdata', args=['--no-sandbox'])page = await browser.newPage()await page.evaluateOnNewDocument('Object.defineProperty(navigator, "webdriver", {get: () => undefined})')await page.goto('https://www.taobao.com')await asyncio.sleep(20)asyncio.run(main())

把  await asyncio.sleep(20) 时间稍微设置长一点,运行之后登录, 然后等结束后,再次运行,就已经处于登陆状态。

问题: 教程里面说会生成一个 userDataDir的文件夹,我这里并没有

如果有,那么关于这个文件夹的介绍可以看官方说明:

https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md

外网,可能打不开

Browser

上面我们了解了 launch 方法,它的返回值是一个 Browser 对选哪个,即浏览器对象, 我们通常将其赋值给 browser 变量(其实就是 Browser 类的一个实例)

下面来看看 Browser 的定义

class pyppeteer.browser.Browser(connection:pyppeteer.connection.Connection, contextIds: LIst[str], ignoreHTTPSErrors:bool, setDefaultViewport:bool, process: Optional[subprocess.Popen] = None, closeCallback: Callable[ [ ] , Awaitable[None] ] = None, **kargs)

从这里可以看出, Browser 有很多参数,大多数情况下直接使用 launch 方法或 connect 方法构造浏览器对象即可

browser 作为 Browser 类的实例, 自然有很多操作浏览器的方法,下面我们来看一些常用的

开启无痕模式

可以通过 createIncognitoBrowserContext 方法开启无痕模式

import asyncio
from pyppeteer import launchwidth,height = 1200, 768async def main():browser = await launch(headless=False,args=['--disable-infobars', f'window-size={width}, {height}'])context = await browser.createIncognitoBrowserContext()page = await context.newPage()await page.setViewport({'width': width, 'height': height})await page.goto('https://www.baidu.com')await asyncio.sleep(100)asyncio.run(main())

这里调用的就是 browser 的 createIncognitoBrowserContext 方法, 返回值是一个 context 对象,利用 context 对象可以新建选项卡

关闭

使用之后调用 close 方法 关闭浏览器,减少开销

import asyncio
from pyppeteer import launchwidth,height = 1200, 768async def main():browser = await launch()page = await browser.newPage()await page.goto('https://spa2.scrape.center/')await asyncio.sleep(10)await browser.close()asyncio.run(main())

page

page 即页面, 对应一个选项卡, 一个网页

选择器

page 对象内置了很多用于选取节点的选择器方法, 例如 J (大写的 j ), 给它传入一个选择器,就能返回匹配到的第一个个节点, 等价于 querySelector 方法, 有 JJ 方法, 给它传入选择器,就会返回所有符合选择器条件的节点列表, 等价于 querySelectorAll 方法

import asyncio
from pyppeteer import launchasync def main():browser = await launch()page = await browser.newPage()await page.goto('https://spa2.scrape.center/')await page.waitForSelector('.item .name')j_result1 = await page.J('.item .name')j_result2 = await page.querySelector('.item .name')jj_result1 = await page.JJ('.item .name')jj_result2 = await page.querySelectorAll('.item .name')print(j_result1)print(j_result2)print(jj_result1)print(jj_result2)await browser.close()asyncio.run((main()))

<pyppeteer.element_handle.ElementHandle object at 0x000001D668C72A10>
<pyppeteer.element_handle.ElementHandle object at 0x000001D668C779D0>
[<pyppeteer.element_handle.ElementHandle object at 0x000001D668C76850>,

。。。。。 

<pyppeteer.element_handle.ElementHandle object at 0x000001D668C7C350>, <pyppeteer.element_handle.ElementHandle object at 0x000001D668C7C390>]
[<pyppeteer.element_handle.ElementHandle object at 0x000001D668C76610>, <pyppeteer.element_handle.ElementHandle object at 0x000001D668C768D0>, 

。。。。。

<pyppeteer.element_handle.ElementHandle object at 0x000001D668C7D810>]
 

可以看到 J 和 querySelector 方法返回的都是 ElementHandle 队形

JJ 和 querySelectorAll 方法都是由 ElementHandle 对象组成列表

选项卡操作

前面我们使用了 newPage 新建选项卡, 新建之后怎么获取和切换

先调用 pages 方法 获取所有打开的页面,然后选择其中一个页面调用 bringToFront 方法

import asyncio
from pyppeteer import launchasync def main():browser = await launch(headless=False)page = await browser.newPage()await page.goto('https://www.baidu.com')page = await browser.newPage()await page.goto('https://www.bing.com')pages = await browser.pages()print('Pages: ', pages)page1 = pages[1]await page1.bringToFront()await asyncio.sleep(30)await browser.close()asyncio.run((main()))

这里先启动了 Pyppeteer , 然后调用了 newPage 方法新建了两个选项卡,并访问了两个网站,然后切换回了第一个选项卡

页面操作

页面的 加载, 前进,后退,关闭,保存

import asyncio
from pyppeteer import launchasync def main():browser = await launch(headless=False)page = await browser.newPage()await page.goto('https://www.baidu.com/')await page.goto('https://spa2.scrape.center/')# # 后退await page.goBack()# # 前进# await page.goForward()# # 刷新await page.reload()# # 保存 PDF# await page.pdf()# # 截图await page.screenshot()# # 设置页面 HTMLawait page.setContent('<h2>Hello world </h2>')# # 设置 User-Agentawait page.setUserAgent('Python')# # 设置 headersawait page.setExtraHTTPHeaders(headers={})# # 关闭await page.close()await browser.close()

其中 前进 和 保存 PDF 有点问题

点击

点击调用 click 方法即可

import asyncio
from pyppeteer import launchasync def main():browser = await launch(headless=False)page = await browser.newPage()await page.goto('https://spa2.scrape.center/')await page.waitForSelector('.item .name')await page.click('.item .name', options={'button': 'left','clickCount': 1,  # 1 或 2'delay': 3000  # 毫秒})await browser.close()asyncio.run(main())

这里 click 方法中第一个参数就是选择器, 即在哪里操作。 第二个参数是几项配置,具体如下

button : 鼠标按钮, 取值有 left  , middle , right

clickCount: 点击次数,  取值有 1 或2 表示 单击或双击

delay: 延迟点击

输入文本

使用 type 方法即可

import asyncio
from pyppeteer import launch
import timeasync def main():browser = await launch(headless=False)page = await browser.newPage()await page.goto('https://www.taobao.com')await page.type('#q', 'iPad')time.sleep(10)await browser.close()asyncio.run(main())

type 第一个参数是选择器, 第二个参数是要输入的内容

获取信息

Page 对象需要调用 content 方法获取源代码, Cookies 对象调用 cookies 方法获取

import asyncio
from pyppeteer import launchasync def main():browser = await launch(headless=False)page = await browser.newPage()print('HTML: ', await page.content())print('Cookies: ', await page.cookies())await browser.close()asyncio.run(main())

执行 JavaScript

pyppeteer 可以执行 JavaScript 语句, 使用 evaluate 即可

import asyncio
from pyppeteer import launchwidth,height = 1366, 768async def main():browser = await launch(headless=False)page = await browser.newPage()await page.setViewport({'width': width, 'height': height})await page.goto('https://spa2.scrape.center/')await page.waitForSelector('.item .name')await asyncio.sleep(2)await page.screenshot(path='example.png')dimensions = await page.evaluate(""" () => {return {width: document.documentElement.clientWidth,height: document.documentElement.clientHeight}}""")print(dimensions)await browser.close()asyncio.run(main())

这里我们调用了 evaluate 方法执行 JavaScript 语句, 并获取了结果, 另外 , Pyppeteer 还有

exposeFunction ,  evaluateOnNewDocument, evaluateHandle 方法,可以了解一下

延时等待

本页最开始的地方,我们演示了 waitForSelector 的用法, 它可以让页面等待某些符合条件的节点加载出来之后再返回结果。 这里我们给 waitForSelector 传入一个 CSS 选择器, 如果找到符合条件的节点,就立马返回结果,否则等待直到超时

除了 waitForSelector 还有很多其他等待方法

waitForFunction :  等待某个 JavaScript 方法执行完毕后返回结果

waitForNavigation : 等待页面跳转,如果没加载出来,就报错

waitForRequest ; 等待某个特定的请求发出

waitForResponse :  等待某个特定请求对应的响应

waitFor: 通用的等待方法

waitForXpath : 等待符合 XPaht 的节点加载出来

总结: pyppeteer 还有很多其他功能, 例如 键盘事件, 鼠标事件, 对话框事件等等

具体参考官网:

https://miyakogi.github.io/pyppeteer/reference.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/51016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.net 连接达梦数据库开发环境部署

.net 开发环境部署 1. 环境准备 测试工具 Visual Studio2022 数据库版本 dm8 2. 搭建过程 1 &#xff09;创建新项目 2 &#xff09;选择创建空项目 3 &#xff09;配置新项目 4 &#xff09;右键 DM1 新建一个项 5 &#xff09;加 载 驱 动 &#xff0c; 新 建 …

0722_驱动3 地址映射驱动点灯

一、为什么需要地址映射 在芯片手册上查看到的地址属于物理地址&#xff0c;在硬件层 在内核空间地址属于虚拟地址&#xff0c;在内核层 在驱动中&#xff0c;操作的是虚拟地址 需要将物理地址《--mmu内存管理单元--》虚拟地址映射 二、映射API接口 void *ioremap(unsigned lon…

backtrace

介绍 arm平台的调用栈与x86平台的调用栈大致相同&#xff0c;稍微有些区别&#xff0c;主要在于栈帧的压栈内容和传参方式不同。在arm平台的不同程序&#xff0c;采用的编译选项不同&#xff0c;程序运行期间的栈帧也会不同。有些工具在对arm的调用栈回溯时&#xff0c;可能会…

电商项目之如何判断线程池是否执行完所有任务

文章目录 1 问题背景2 前言3 4种常用的方法4 代码4.1 isTerminated()4.2 线程池的任务总数是否等于已执行的任务数4.3 CountDownLatch计数器4.4 CyclicBarrier计数器 1 问题背景 真实生产环境的电商项目&#xff0c;常使用线程池应用于执行大批量操作达到高性能的效果。应用场景…

Dify中语音和文字间转换问题的一种暂时注释方式

本文主要解释了Dify中语音和文字间转换可能会遇到的问题&#xff0c;并给出了一种暂时注释的解决方案。 一.文本转语音可能问题 本地部署文本转语音时&#xff0c;如果遇到如下问题&#xff0c;安装ffmpeg即可。但是如果安装后&#xff0c;重启系统还是遇到这个问题该如何办&…

分库分表——从理论到最佳实践

目录 1、为什么要分库分表&#xff1f;2、切分方案有哪些&#xff1f;2.1 分库2.1.1 垂直分库2.1.2 水平分库 2.2 分表2.2.1 垂直分表2.2.2 水平分表 2.3 分库分表 3、数据水平分片方法3.1 Hash分片3.2 一致性Hash分片3.3 Range分片 4、分库分表的挑战4.1 分布式id4.2 分布式事…

LLM:归一化 总结

一、Batch Normalization 原理 Batch Normalization 是一种用于加速神经网络训练并提高稳定性的技术。它通过在每一层网络的激活值上进行归一化处理&#xff0c;使得每一层的输入分布更加稳定&#xff0c;从而加速训练过程&#xff0c;并且减轻了对参数初始化的依赖。 公式 …

分类模型——逻辑回归和Fisher线性判别分析

个人学习笔记&#xff0c;课程为数学建模清风付费课程 目录 一、引例 二、逻辑回归 2.1线性概率模型 2.2Fisher线性判别分析 2.3两点分布&#xff08;伯努利分布&#xff09; 2.4连接函数的取法 2.5如何求解 2.6如何用于分类 三、SPSS 3.1二元分类 3.1.1逻辑回…

MySQL内如何改变编码格式

查找数据库的编码格式&#xff1a; show variables like character%;具体内容时这些 在创建表时设定编码格式&#xff1a; create database <要创建的数据库的名字> charset utf8; 修改数据库默认编码&#xff1a; set character_set_databaseutf8mb4; character_…

eclipse ui bug

eclipse ui bug界面缺陷&#xff0c;可能项目过多&#xff0c;特别maven项目过多&#xff0c;下载&#xff0c;自动编译&#xff0c;加载更新界面异常 所有窗口死活Restore不回去了 1&#xff09;尝试创建项目&#xff0c;还原界面&#xff0c;失败 2&#xff09;关闭所有窗口&…

将TP5链接导入笔影个人博客代码

首先第一步&#xff0c;打开界面 第二步&#xff0c;这里卡住了&#xff0c;无法看到源代码&#xff0c;我们使用其他软件看看源代码 调试乱码&#xff0c;因为没有找到相应的笔影个人博客源码。源码在桌面上。询问百度&#xff0c;说了有的没的一大堆。 尝试的结果就是失败…

时间复杂度与O(n)

文章目录 1 复杂度分析1.1 时间复杂度1.1.1 循环执行次数1.1.2 大O(n)表示法 1.2 空间复杂度 1 复杂度分析 1.1 时间复杂度 ​ 时间复杂度用来表示算法运行时间的长短&#xff0c;用来定性的描述程序的运行时间。要了解时间复杂度&#xff0c;我们需要先了解程序执行的次数。…

机器学习(二十二):精度和召回率

一、倾斜数据集 倾斜数据集&#xff1a;一个数据集中的正面和负面例子的比例非常不平衡&#xff0c;比如数据集中&#xff0c;结果为1的占比20%&#xff0c;结果为0的占比80% 例子&#xff1a;如果数据集的结果中只有0.5%是1&#xff0c;其余结果是0。有一个模型的预测准确度…

【信创】udisk2服务异常导致U盘使用中自动移除问题解决

原文链接&#xff1a;【信创】udisk2服务异常导致U盘使用中自动移除问题解决 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在信创终端操作系统上由于udisk2服务异常导致U盘等移动设备在使用中自动移除问题的排查文章。udisk2是一个管理存储设备的服务&#xf…

【计算机网络】OSPF单区域实验

一&#xff1a;实验目的 1&#xff1a;掌握在路由器上配置OSPF单区域。 2&#xff1a;学习OSPF协议的原理&#xff0c;及其网络拓扑结构改变后的变化。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS交换机、网线、内网网卡接口、Windows 2019操作系统的计算机等。…

Vue 3 实现左侧列表点击跳转滚动到右侧对应区域的功能

使用 Vue 3 实现左侧列表点击跳转到右侧对应区域的功能 1. 引言 在这篇博客中&#xff0c;我们将展示如何使用 Vue 3 实现一个简单的页面布局&#xff0c;其中左侧是一个列表&#xff0c;点击列表项时&#xff0c;右侧会平滑滚动到对应的内容区域。这种布局在很多应用场景中都…

Llama 3.1 405B 详解

2024 年 7 月 23 日星期二&#xff0c;Meta 宣布推出 Llama 3.1&#xff0c;这是其Llama 系列大型语言模型 (LLM)的最新版本。虽然只是对 Llama 3 模型进行小幅更新&#xff0c;但它特别引入了Llama 3.1 405B——一个 4050 亿参数的模型&#xff0c;这是迄今为止世界上最大的开…

运行ruoyi

nacos 数据库配置 修改nacos/conf/application.properties 单机版运行 startup.cmd -m standalone redis 运行后端 运行gateway,auth,modules/system模块 可能遇到的问题&#xff1a;端口正在使用 解决 netstat -ano | findstr 9200 taskkill -pid 18284 -f

JAVA同城圈子达人交友系统源码支持微信小程序+公众号+H5+APP

&#x1f308; 同城圈子达人交友系统&#xff0c;遇见志同道合的TA&#xff01; &#x1f389; 开篇&#xff1a;告别孤单&#xff0c;同城圈子等你来探索&#xff01; 在这个快节奏的城市生活中&#xff0c;你是否常常感到孤独&#xff0c;渴望找到一群志同道合的朋友&#…

Elasticsearch基础(六):使用Kibana Lens进行数据可视化

文章目录 使用Kibana Lens进行数据可视化 一、进入Kibana Lens 二、基础可视化 1、指标可视化 2、垂直堆积条形图 3、表格 三、高级可视化 1、多图层和索引 2、子桶 3、树状图 使用Kibana Lens进行数据可视化 一、进入Kibana Lens 在Kibana主页&#xff0c;单击页面…