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

python爬虫------- Selenium下篇(二十三天)

🎈🎈作者主页: 喔的嘛呀🎈🎈
🎈🎈所属专栏:python爬虫学习🎈🎈
✨✨谢谢大家捧场,祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天开心哦!✨✨ 

 

目录

十、处理动态内容

十一、处理验证码

十二、模拟登录

十三、跨页面操作

十四、异常处理

十五、数据存储

存储到文件(例如 CSV 文件)

存储到数据库(例如 SQLite)

存储到其他存储介质(例如 MongoDB)

十六、反爬虫策略

十七、性能优化

十八、定时任务:

十九、 与其他库和工具的集成


helllo,兄弟姐妹们!今天我们接着把第二十二天剩下的十个知识点学完(从第十个开始)。

十、处理动态内容

处理动态加载内容的常见方法是通过模拟用户操作来触发页面加载新内容。对于需要滚动页面加载的情况,可以使用 Selenium 的 execute_script 方法来执行 JavaScript 代码,从而实现滚动页面的效果。下面是一个示例代码,演示如何使用 Selenium 模拟滚动页面来加载更多内容:


from selenium import webdriver
import time# 启动浏览器
driver = webdriver.Chrome()# 打开网页
driver.get('<https://example.com>')# 模拟滚动页面
scroll_pause_time = 2  # 每次滚动后等待时间
screen_height = driver.execute_script("return window.screen.height;")   # 获取屏幕高度i = 1
while True:# 记录滚动前页面高度last_height = driver.execute_script("return document.body.scrollHeight;")# 模拟滚动到页面底部driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")# 等待页面加载time.sleep(scroll_pause_time)# 计算新的页面高度new_height = driver.execute_script("return document.body.scrollHeight;")# 如果新的页面高度和上次相同,则说明已经滚动到底部if new_height == last_height:break# 打印滚动次数print(f"Scrolling {i} times")i += 1# 获取页面数据
data = driver.page_source# 关闭浏览器
driver.quit()# 处理页面数据,如解析数据等

在这个示例中,我们首先启动 Chrome 浏览器,并打开了一个示例网页。然后,我们通过执行 JavaScript 代码来模拟滚动页面到底部的效果。在每次滚动后,我们等待了2秒钟以确保页面有足够的时间加载新内容。如果页面高度不再增加,说明已经滚动到了页面底部,循环就会结束。最后,我们获取了页面的 HTML 源码,并可以继续处理数据,如解析数据等操作。

请注意,这只是一个简单的示例。实际情况可能会更复杂,具体取决于要爬取的网站和其动态加载数据的机制。

十一、处理验证码

处理网页中的验证码通常需要结合 Selenium 和图像识别技术。下面是一个使用 Selenium 和 pytesseract 库来处理网页中简单验证码的示例:

首先,安装 Pillow、pytesseract 和 pytesseract 库:


pip install Pillow pytesseract selenium

然后,下载并安装 Tesseract OCR,并将其添加到系统路径中。

接下来,使用以下代码示例:


from PIL import Image
import pytesseract
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import requests
from io import BytesIO# 设置 Tesseract OCR 路径
pytesseract.pytesseract.tesseract_cmd = r'C:\\Program Files\\Tesseract-OCR\\tesseract.exe'# 启动浏览器
driver = webdriver.Chrome()# 打开网页
driver.get('<https://example.com>')# 找到验证码图片元素
captcha_element = driver.find_element(By.XPATH, '//img[@id="captcha-image"]')# 获取验证码图片的链接
captcha_image_url = captcha_element.get_attribute('src')# 下载验证码图片
response = requests.get(captcha_image_url)
captcha_image = Image.open(BytesIO(response.content))# 识别验证码
captcha_text = pytesseract.image_to_string(captcha_image)# 输入验证码
captcha_input = driver.find_element(By.XPATH, '//input[@id="captcha-input"]')
captcha_input.send_keys(captcha_text)# 提交表单
submit_button = driver.find_element(By.XPATH, '//button[@id="submit-button"]')
submit_button.click()# 等待页面加载
time.sleep(2)# 获取页面数据
data = driver.page_source# 关闭浏览器
driver.quit()# 处理页面数据,如解析数据等

在这个示例中,我们首先设置了 Tesseract OCR 的路径。然后,使用 Selenium 打开了一个示例网页,并找到了验证码图片元素。我们通过请求验证码图片的链接,并使用 pytesseract 库识别验证码中的文本。最后,我们将识别结果填写到验证码输入框中,并提交表单。

请注意,这只适用于简单的验证码。对于复杂的验证码,可能需要使用更复杂的技术和工具。

注意:

Tesseract OCR(Optical Character Recognition)是一个开源的光学字符识别引擎,由 Google 开发并维护。它能够将图像中的文字转换为可编辑的文本。Tesseract 能够识别超过100种语言的文字,并且支持许多图像格式。Tesseract 的最新版本是4.x,具有比较高的准确性和性能。

使用 Tesseract OCR 进行文本识别通常涉及以下步骤:

  1. 安装 Tesseract OCR:根据您的操作系统下载并安装 Tesseract OCR。对于 Windows 系统,可以从 GitHub Release 页面下载安装包进行安装。对于 macOS 和 Linux 系统,可以通过包管理器(如 Homebrew 或 apt)安装。

  2. 安装 pytesseract:pytesseract 是一个 Python 模块,用于与 Tesseract OCR 进行交互。您可以使用 pip 安装 pytesseract:

    bashCopy code
    pip install pytesseract
  3. 使用 pytesseract 进行图像文本识别:下面是一个简单的示例代码,演示如何使用 pytesseract 对图像进行文本识别:

    
    from PIL import Image
    import pytesseract# 读取图像文件
    image = Image.open('example.png')# 使用 pytesseract 进行文本识别
    text = pytesseract.image_to_string(image)# 打印识别结果
    print(text)

Tesseract OCR 对于特定字体、大小和质量的图像效果可能会有所不同。在实际使用中,我们需要调整图像预处理和 Tesseract 的参数来获得最佳的识别结果。

十二、模拟登录

要使用 Selenium 模拟登录网站并爬取需要登录才能访问的页面,我们可以按照以下步骤进行:

  1. 启动浏览器并打开登录页面。
  2. 填写登录表单,包括用户名和密码。
  3. 点击登录按钮。
  4. 等待登录完成。
  5. 访问需要登录才能访问的页面,提取数据或进行其他操作。

下面是一个示例代码,演示如何使用 Selenium 模拟登录网站并爬取需要登录才能访问的页面:


from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time# 启动浏览器
driver = webdriver.Chrome()# 打开登录页面
driver.get('<https://example.com/login>')# 填写用户名和密码
username_input = driver.find_element(By.ID, 'username')
password_input = driver.find_element(By.ID, 'password')username_input.send_keys('your_username')
password_input.send_keys('your_password')# 提交登录表单
password_input.send_keys(Keys.RETURN)# 等待登录完成,这里假设登录成功后会跳转到首页
time.sleep(2)# 访问需要登录才能访问的页面
driver.get('<https://example.com/protected_page>')# 提取页面数据或进行其他操作
data_element = driver.find_element(By.XPATH, '//div[@class="data"]')
data = data_element.text
print('Protected Page Data:', data)# 关闭浏览器
driver.quit()

请注意,在实际使用中,我们需要替换示例中的 '<https://example.com/login''your_username'> 和 'your_password' 为实际的登录页面 URL、用户名和密码。同时,确保我们的行为符合网站的使用条款和规定,以免触发反爬虫措施。

十三、跨页面操作

处理需要跨页面操作的情况通常需要在页面之间进行导航和交互。使用 Selenium 可以模拟用户在网页上的操作,包括点击链接跳转到另一个页面。下面是一个示例代码,演示如何在一个页面点击链接跳转到另一个页面进行数据提取:


from selenium import webdriver
from selenium.webdriver.common.by import By
import time# 启动浏览器
driver = webdriver.Chrome()# 打开第一个页面
driver.get('<https://example.com/page1>')# 点击页面上的链接
link_element = driver.find_element(By.XPATH, '//a[@id="link-to-page2"]')
link_element.click()# 等待页面加载
time.sleep(2)# 在第二个页面提取数据
data_element = driver.find_element(By.XPATH, '//div[@id="data-on-page2"]')
data = data_element.textprint('Data on page 2:', data)# 关闭浏览器
driver.quit()

在这个示例中,我们首先启动了 Chrome 浏览器,并打开了第一个页面。然后,我们找到了第一个页面上的链接元素,并使用 click() 方法点击了该链接。随后,我们等待了2秒钟,以确保第二个页面加载完成。最后,我们找到了第二个页面上的数据元素,并提取了其文本内容。

需要注意的是,实际情况可能更复杂,具体取决于网站的结构和交互方式。在处理跨页面操作时,确保等待页面加载完成并处理可能的异常情况是很重要的。

十四、异常处理

在爬取过程中,可能会出现各种异常情况,如超时、元素未找到等。为了确保爬虫的稳定性和可靠性,需要对这些异常情况进行处理。下面是一个示例代码,演示如何使用 try-except 语句来处理这些异常情况:


from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC# 启动浏览器
driver = webdriver.Chrome()try:# 设置页面加载超时时间为10秒driver.set_page_load_timeout(10)# 打开网页driver.get('<https://example.com>')# 显式等待10秒,直到元素加载完成WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//div[@id="content"]')))# 提取数据content_element = driver.find_element(By.XPATH, '//div[@id="content"]')content = content_element.textprint('Content:', content)except TimeoutException:print('页面加载超时')except NoSuchElementException:print('元素未找到')finally:# 关闭浏览器driver.quit()

在这个示例中,我们使用了 try-except 语句来捕获可能出现的 TimeoutException(超时异常)和 NoSuchElementException(元素未找到异常)。在 try 代码块中,我们设置了页面加载超时时间为10秒,并使用显式等待来等待页面元素加载完成。如果页面加载超时或元素未找到,则会相应地捕获并处理异常。最后,无论是否发生异常,我们都会在 finally 代码块中关闭浏览器。

通过合理地处理异常情况,可以使爬虫在遇到问题时能够优雅地处理,并继续执行其他操作。

十五、数据存储

提取到的数据存储到文件、数据库或其他存储介质中是网页爬取的重要步骤之一。具体的存储方式取决于您的需求和项目的要求。以下是几种常见的数据存储方式示例:

存储到文件(例如 CSV 文件)


import csvdata = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]with open('data.csv', mode='w', newline='') as file:writer = csv.DictWriter(file, fieldnames=['name', 'age'])writer.writeheader()for row in data:writer.writerow(row)

存储到数据库(例如 SQLite)


import sqlite3data = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]conn = sqlite3.connect('data.db')
cursor = conn.cursor()cursor.execute('''CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)''')for row in data:cursor.execute('INSERT INTO users (name, age) VALUES (?, ?)', (row['name'], row['age']))conn.commit()
conn.close()

存储到其他存储介质(例如 MongoDB)


from pymongo import MongoClientdata = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]client = MongoClient('mongodb://localhost:27017/')
db = client['mydatabase']
collection = db['users']for row in data:collection.insert_one(row)client.close()

这些示例展示了如何将提取到的数据存储到不同的存储介质中。您可以根据项目的需要选择适合的存储方式。

十六、反爬虫策略

反爬虫策略是网站为防止被爬虫程序恶意抓取数据而采取的一系列措施。常见的反爬虫策略包括:

  1. User-Agent检测:网站会检查请求中的 User-Agent 字段,如果发现是爬虫程序常用的 User-Agent,则可能拒绝服务或返回特定响应。
  2. IP地址限制:网站可能会限制同一IP地址的访问频率,过高频率的访问会被视为异常行为。
  3. 验证码:网站可能会在某些操作前要求用户输入验证码,以确认访问者是人类而不是爬虫程序。
  4. 动态加载内容:网站使用JavaScript等技术来动态加载内容,使得只有通过真正执行页面脚本才能获取到完整内容。
  5. 频率限制:限制同一用户或IP地址在一定时间内的请求频率,过高频率的请求会被拒绝。
  6. 页面结构变化:定期改变页面结构,使得爬虫程序难以适应变化而失效。

应对这些反爬虫策略的方法包括:

  1. 设置合理的User-Agent:模拟浏览器行为,避免使用常见的爬虫User-Agent。
  2. 使用代理IP:使用代理IP来隐藏真实IP地址,避免被网站封禁。
  3. 处理验证码:使用验证码识别技术自动处理验证码。
  4. 限制访问频率:设置合理的访问间隔时间,避免过高频率的访问。
  5. 使用随机延迟:在请求之间添加随机延迟,模拟人类操作。
  6. 动态解析页面:使用动态解析技术获取动态加载的内容。
  7. 定期监测网站变化:定期检查网站结构的变化,及时调整爬取策略。
  8. 遵守robots.txt规范:遵守网站的robots.txt文件中的规定,不访问被禁止的页面。

综上所述,应对反爬虫策略需要综合考虑网站的具体情况和采取合适的应对策略。

十七、性能优化

当涉及性能优化时,代码中的优化通常是特定于应用程序和场景的。下面是一些常见的Python爬虫代码优化技巧示例:

(1)减少不必要的等待时间:避免使用固定的等待时间,而是根据需要进行动态等待。示例代码:


from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECdriver = webdriver.Chrome()
driver.get("<https://example.com>")try:element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "myElement")))
finally:driver.quit()

(2)合理使用隐式等待:在创建WebDriver实例时设置隐式等待时间,而不是在每个操作中都设置等待时间。示例代码:


from selenium import webdriverdriver = webdriver.Chrome()
driver.implicitly_wait(10) # 设置隐式等待时间为10秒driver.get("<https://example.com>")
element = driver.find_element(By.ID, "myElement")

(3)使用多线程/异步处理:使用**concurrent.futures**模块进行异步处理。示例代码:


from concurrent.futures import ThreadPoolExecutor
from selenium import webdriverdef scrape(url):driver = webdriver.Chrome()driver.get(url)# 爬取逻辑driver.quit()urls = ['<https://example.com/page1>', '<https://example.com/page2>', '<https://example.com/page3>']with ThreadPoolExecutor(max_workers=5) as executor:executor.map(scrape, urls)

(4)避免重复请求:使用缓存来存储已经爬取过的数据。示例代码:


import requests
import hashlibcache = {}def get_data(url):if url in cache:return cache[url]response = requests.get(url)data = response.textcache[url] = datareturn dataurl = '<https://example.com>'
data = get_data(url)

这些示例代码演示了一些常见的Python爬虫代码优化技巧,但实际的优化策略应根据具体的爬虫应用程序和场景进行调整和优化。

十八、定时任务:

要将爬虫任务设置为定时执行,可以使用Python的**schedule库来实现。schedule库可以帮助我们在指定的时间间隔内定期运行任务。以下是一个简单的示例代码,演示如何使用schedule**库来定时执行爬虫任务:


import schedule
import timedef crawl():# 在这里编写爬虫逻辑print("开始爬取数据...")# 每小时执行一次爬虫任务
schedule.every().hour.do(crawl)# 在这里可以设置其他定时任务,如每天、每周等# 保持程序运行,直到手动终止
while True:schedule.run_pending()time.sleep(1)

在这个示例中,**crawl函数是我们的爬虫逻辑。使用schedule.every().hour.do(crawl)来设置每小时执行一次爬虫任务。您还可以使用其他schedule.every()**方法来设置其他的定时任务,如每天、每周等。

请注意,为了保持程序持续运行,我们使用了一个**while True循环来不断检查是否有定时任务需要执行,并使用time.sleep(1)**来让程序每秒钟检查一次。这样可以确保定时任务能够按照预期执行。

十九、 与其他库和工具的集成

将Selenium与其他库和工具集成可以实现更强大的功能,比如使用BeautifulSoup解析页面内容、使用pandas处理数据等。以下是一个示例代码,演示了如何将Selenium与BeautifulSoup和pandas集成:

pythonCopy code
from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd# 启动浏览器
driver = webdriver.Chrome()# 打开网页
driver.get('<https://example.com>')# 获取页面源码
html = driver.page_source# 使用BeautifulSoup解析页面
soup = BeautifulSoup(html, 'html.parser')# 提取需要的数据
data = []
for item in soup.find_all('div', class_='item'):name = item.find('h2').textprice = item.find('span', class_='price').textdata.append({'name': name, 'price': price})# 将数据转换为DataFrame
df = pd.DataFrame(data)# 关闭浏览器
driver.quit()# 打印数据
print(df)

在这个示例中,我们首先使用Selenium打开了一个网页,并获取了页面的源码。然后,我们使用BeautifulSoup解析了页面,并提取了需要的数据。最后,我们使用pandas将数据转换为DataFrame,并进行打印输出。这样,就实现了将Selenium与BeautifulSoup和pandas集成的功能。

好了,今天的学习就到这里了,第二十四天会带来几个案例将上面的知识点运用起来。敬请期待!拜拜啦!

相关文章:

python爬虫------- Selenium下篇(二十三天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…...

获取字符串的全排列(去除字符串中2个字符相同时造成的重复)

一、概念 现有一个字符串&#xff0c;要打印出该字符串中字符的全排列。 以字符串abc为例&#xff0c;输出的结果为&#xff1a;abc、acb、bac、bca、cab、cba。 以字符串aab为例&#xff0c;输出的结果为&#xff1a;aab、aba、baa。 二、代码 public class Permutation {pub…...

HTML5新增的多媒体标签

在网页中加入音乐 <audio></audio> src 设置音乐文件名以及路径,<audio>标记支持MP3、WAV及OGG 3种音乐格式 autoplay&#xff1a;是否自动播放,加入autopaly属性表示自动播放 controls&#xff1a; 是否显示播放面板,加入controls属性表示显示播放面板 …...

温湿度传感器(DHT11)以及光照强度传感器(BH1750)的使用

前言 对于一些单片机类的环境检测或者智能家居小项目中&#xff0c;温湿度传感器&#xff08;DHT11&#xff09;以及光照强度传感器&#xff08;BH1750&#xff09;往往是必不可少的两个外设&#xff0c;下面我们来剖析这两个外设的原理&#xff0c;以及使用。 1. 温湿度传感…...

ActiveMQ 04 Linux下安装

Active MQ 04 Linux下安装 下载 解压 在init.d下建立软连接 ln -s /usr/local/activemq/bin/activemq ./设置开启启动 chkconfig activemq on 服务管理 service activemq start service activemq status service activemq stopNIO配置 默认配置为tcp&#xff0c;使用的…...

.pyc 文件是什么?是否有必要同步到 GitHub 远程仓库?

git status 时发现有很多 .pyc 的没有被 add (env) username:~/path/to/project$ git status On branch main Your branch is up to date with origin/main.Changes to be committed:(use "git restore --staged <file>..." to unstage)new file: xxx.pyCha…...

Zookeeper的集群搭建和ZAB协议详解

Zookeeper的集群搭建 1&#xff09;zk集群中的角色 Zookeeper集群中的节点有三个角色&#xff1a; Leader&#xff1a;处理集群的所有事务请求&#xff0c;集群中只有一个LeaderFollwoer&#xff1a;只能处理读请求&#xff0c;参与Leader选举Observer&#xff1a;只能处理读…...

STM32 MPU配置参数

TXE LEVEL一般只用MPU_TEX_LEVEL0 1 - 1 - 1 -0性能最强&#xff08;TEX - C - B- S&#xff09;. #define MPU_TEX_LEVEL0 ((uint8_t)0x00) #define MPU_TEX_LEVEL1 ((uint8_t)0x01) #define MPU_TEX_LEVEL2 ((uint8_t)0x02) 基于上表进行常用配置 &#xff…...

Kafka概述

目录 1、为什么需要消息队列&#xff08;MQ&#xff09; 2、使用消息队列的好处 3、消息队列的两种模式 4、Kafka 定义 5、Kafka 简介 6、Kafka 的特性 7、Kafka 系统架构 8、Partation 数据路由规则 9、分区的原因 1、为什么需要消息队列&#xff08;MQ&#xff09; …...

OpenHarmony编译构建系统

这篇来聊聊OpenHarmony的编译构建&#xff0c;经过前面的实践&#xff0c;再来看编译构建。 编译构建概述 在官网中提到了&#xff0c;OpenHarmony编译子系统是以GN和Ninja构建为基座&#xff0c;对构建和配置粒度进行部件化抽象、对内建模块进行功能增强、对业务模块进行功能…...

Qt5 编译oracle数据库驱动

库文件 1、Qt源码目录&#xff1a;D:\Qt5\5.15.2\Src\qtbase\src\plugins\sqldrivers\oci 2、oracle客户端SDK: https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html 下载各版本中的如下压缩包&#xff0c;一定要版本相同的 将两个压缩包…...

UE5学习日记——实现自定义输入及监听输入,组合出不同的按键输入~

UE5的自定义按键和UE4有所不同&#xff0c;在这里记录一下。 本文主要是记录如何设置UE5的自定义按键&#xff0c;重点是学会原理&#xff0c;实际开发时结合实际情况操作。 输入映射 1. 创建输入操作 输入操作并不是具体的按键映射&#xff0c;而是按键的激活方式&#xff0…...

为什么把script标签放在div下面?

放在底部可以优先加载页面的内容结构,提升页面渲染速度。只有等到HTML解析完成后,才会开始执行main.js,避免JS阻塞页面解析&#xff0c; 同时main.js里可能会操作DOM,如果放头部,可能会找不到节点而报错 <body><div id"root"><App></App>&l…...

Git 自定义命令

前言 在使用 hexo 搭建个人博客时&#xff0c;共两种部署的方法。分别为&#xff1a; 本地利用 hexo 的插件 hexo-deployer-git 来实现部署&#xff0c;缺点是需要多敲几个命令行且不方便对源码进行云端备份使用 Github Action 的 workflow 自动化部署&#xff0c;优势就是可…...

SpringBoot多数据源配置及使用

1.application.properties数据配置 首先现在配置文件中定义三个数据库相关信息 # 数据库1 targetLibraryMain.datasource.url jdbc:kingbase8://127.0.0.1:54321/DATA_ONE?useUnicodetrue&characterEncodingutf8&serverTimezoneGMT%2B8&allowMultiQueriestrue …...

12-项目部署_持续集成

项目部署_持续集成 1 今日内容介绍 1.1 什么是持续集成 持续集成&#xff08; Continuous integration &#xff0c; 简称 CI &#xff09;指的是&#xff0c;频繁地&#xff08;一天多次&#xff09;将代码集成到主干 持续集成的组成要素 一个自动构建过程&#xff0c; 从…...

文献阅读:LESS: Selecting Influential Data for Targeted Instruction Tuning

文献阅读&#xff1a;LESS: Selecting Influential Data for Targeted Instruction Tuning 1. 文章简介2. 方法介绍 1. Overview2. 原理说明 1. SGD上的定义2. Adam上的定义 3. 具体实现 1. Overview1. LoRA使用2. 数据选择3. LESS-T 3. 实验考察 & 结论 1. 实验设计2. 主…...

应对中年危机-高效学习

兴致勃勃的打开一本书&#xff0c;从第一行&#xff0c;第一个字开始&#xff0c;十分钟later……两眼皮一塌&#xff0c;哎&#xff0c;想睡觉了&#xff0c;真助眠。但其实我并不懒啊。 过去我是上诉这样&#xff0c;现在有了改善。如果你也是这样&#xff0c;希望看完了本文…...

Java二叉树(2)

一、二叉树的链式存储 二叉树的存储分为顺序存储和链式存储 &#xff08;本文主要讲解链式存储&#xff09; 二叉树的链式存储是通过一个一个节点引用起来的&#xff0c;常见的表示方式有二叉三叉 // 孩子表示法 class Node { int val; // 数据域 Node left; // 左孩子的引用…...

关于AG32 MCU的一些奇思妙想

1、AG32VF103的网口是100M还是10M&#xff1f; RE: 都是100M的。 2、用FPGA能不能再仿出一个网口&#xff1f;有些产品用到两个网口。 理论上可以&#xff0c;但是要考虑&#xff0c;一个是cpld实现难度&#xff0c;一个是需要的逻辑单元。因为mac逻辑多&#xff0c;内置的2KL…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...