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

爬虫学习记录

 1.概念

通过编写程序,模拟浏览器上网,然后让其去互联网上抓取数据的过程

  • 通用爬虫:抓取的是一整张页面数据
  • 聚焦爬虫:抓取的是页面中的特定局部内容
  • 增量式爬虫:监测网站中数据更新的情况,只会抓取网站中最新更新出来的数据

robots.txt协议:

君子协议,网站后面添加robotx.txt可进行查看

https://www.baidu.com/robots.txt

1.1 http协议

服务器和客户端进行数据交互的一种形式

常用的请求头信息:

  • User-Agent: 请求载体的身份标识,如: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36
  • Connection: 请求完毕完毕之后,是断开连接还是保持连接(close和keep-alive)

常用响应头信息:

  • Content-Type: 服务器响应客户端的数据类型 如:(text/html; charset=utf-8)

1.2 https协议

安全的超文本传输协议,在客户端和服务端进行数据传输和数据交互的过程中,数据是进行加密的.

数据加密的方式

  • 对称秘钥加密: 客户端制定加密方式,加加密的密文和生成的秘钥都传输给服务端.服务端根据秘钥对于密文进行解密.(但是密文和秘钥可能会被同时拦截)
  • 非对称秘钥加密:服务端生成秘钥对,将生成的公钥传递给客户端,然后将生成的密文传递给服务端,服务端再使用私钥进行解密(客户端拿到的秘钥,不一定是从服务端传递过来的)
  • 证书秘钥加密:服务器端制定加密方式,服务端将公钥传递给证书认证机构,认证机构将公钥通过认证之后,进行数字签名.将携带数字签名的公钥封装到证书当中,将证书一并发送给客户端

2. requests模块

作用:模拟浏览器发送请求

requests模块的编码流程:

  • 指定url
  • 发起请求(get/post)
  • 获取相应数据
  • 持久化存储

2.1 简易网页采集器

2.1.1 UA 伪装

将python脚本发送的请求,伪装成为浏览器发送的请求

2.1.2 Get请求携带参数

将url的参数封装成为字典,传递给params

# _*_ coding utf-8 _*_
# george
# time: 2024/12/24下午7:56
# name: test.py
# comment:
import requests# 参考url
# https://www.baidu.com/s?wd=%E6%88%90%E5%8A%9F
url = "https://www.baidu.com/s?"# UA伪装:模拟浏览器
header = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
}word = input("enter your word:").strip()# get请求携带的参数
param = {"wd":word
}# 获取响应对象
response = requests.get(url, headers=header, params=param)# 获取响应内容,可以通过response.text获取字符串形式的响应数据
page_text = response.content# 持久化储存
file_name = word + ".html"
with open(file_name, "wb") as f:f.write(page_text)print(f"{file_name} has been save successfully")

2.2 破解百度翻译

2.2.1 POST请求携带参数

将传递的参数封装成为字典,并且传递给data

180e7e948fa9407cb8ffb152aa6caa93.png

2.2.2 Ajax请求

单词输入后,局部页面就会刷新

Ajax(Asynchronous JavaScript and XML)是一种在Web应用程序中进行异步通信的技术,它使用JavaScript和XML(现在通常使用JSON)来实现在不刷新整个页面的情况下与服务器进行数据交换

97db308ad6cc45dfa31e7f16dcee5cc8.png

2.2.3 JSON模块的使用

  • 反序列化 loads:将json字符串转化为python对象字典
  • 序列化 dump: 将python对象字典转化为json字符串,并写入文件

4c96e3dfa22742a1a2ce45a179a8f6cd.png

# _*_ coding utf-8 _*_
# george
# time: 2024/12/24下午7:56
# name: test.py
# comment:
import requests
import json# 参考url
url = "https://fanyi.baidu.com/sug"# UA伪装:模拟浏览器
header = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36","Referer":"https://fanyi.baidu.com/mtpe-individual/multimodal"
}word = input("enter your word:").strip()# get请求携带的参数
param = {"kw":word
}# 获取响应对象
response = requests.post(url, headers=header,data=param)# 获取响应内容
word_text = json.loads(response.text)# 持久化储存
file_name = word + ".json"
with open(file_name, "w",encoding="utf-8") as f:json.dump(word_text["data"][0], f,ensure_ascii=False)print(f"{file_name} has been save successfully")

f35d983fa23d484db43827f19e219270.png

2.3 电影 

2.4 公司url

  • 动态加载数据分析
  • 获取每家公司的url,但是发现每家公司的详情页面也是动态加载出来的

3.数据解析

  • 正则
  • bs4
  • xpath

数据解析原理:

解析局部的文本内容都会在标签之间或是标签的属性中进行存储

  • 进行指定标签的定位
  • 标签或是标签对应属性存储值的获取

3.1 正则解析

3.2 bs4解析

只可以被应用于python中

3.2.1 数据解析原理

  • 实例化BeautifulSoup对象,并且将页面源码数据加载到该对象里面
  • 通过调用BeautifulSoup对象中的相关的属性或是方法,进行标签定位和数据提取

3.2.2 环境安装

pip3 install beautifulsoup4  -i  https://mirrors.aliyun.com/pypi/simple
pip3 install lxml  -i  https://mirrors.aliyun.com/pypi/simple

3.2.3 bs4的具体使用

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/12/26 22:07
# @Author : George
from bs4 import BeautifulSoup
import refp = open("./result.html", "r", encoding="utf-8")
soup = BeautifulSoup(fp, "lxml")
# soup.tagName:返回的是html中第一次出现的tag标签
print(soup.div)
# -------------------------------------------
# 等同于soup.tagName
print(soup.find("a"))
# 属性定位
print(soup.find("a", href=re.compile(".*ip138.com/$")).text)
# # 加载源码中所有的tag标签组成的列表
print(soup.find_all("a"))
# -------------------------------------------
# 可以使用选择器,id/类/标签/选择器,返回的是一个列表
print(soup.select('.center'))
# 层级选择器,
# “ ”空格就是表示多个层级
# > 表示一个层级
for i in soup.select('.center > ul > li > a'):print(i.text)
print(soup.select('.center > ul a')[0])
# -------------------------------------------
# 获取标签之间的文本数据 soup.a.text/string/get_text()
# --text/get_text可以获取标签里面啊所有的文本内容
# --string只可以获取该标签下的直系文本内容
print(soup.select('.center > ul a')[0].string)
# -------------------------------------------
# 获取标签里面的属性值
print(soup.select('.center > ul a')[0]["href"])

3.2.4 bs4爬取三国演义

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/12/26 22:43
# @Author : George
# ==================================================
# <a href="/guwen/bookv_6dacadad4420.aspx">第一回</a>
# 第一回网址
# https://www.gushiwen.cn/guwen/bookv_6dacadad4420.aspx
# ==================================================from bs4 import BeautifulSoup
import requestsurl = "https://www.gushiwen.cn/guwen/book_46653FD803893E4F7F702BCF1F7CCE17.aspx"# UA伪装:模拟浏览器
header = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
}
# 获取响应对象
response = requests.get(url, headers=header)
# 实例化bs对象
soup = BeautifulSoup(response.text, "lxml")
a_liat = soup.select(".bookcont >ul > span >a")
fp = open("三国.txt","w",encoding="utf-8")
# 解析章节标题和详情页面的url
for tag in a_liat:title = tag.textdetail_url = "https://www.gushiwen.cn/"+tag["href"]# 对详情页面发起请求detail_page = requests.get(detail_url, headers=header)# 解析出详情页面中的内容detail_soup = BeautifulSoup(detail_page.text,"lxml")# 使用此种方法出现一个问题,就是文章都是在p标签里面,所以文章不会换行# content = detail_soup.find("div",class_="contson").textfp.write(title + ":")for line in detail_soup.select('.contson > p'):fp.write(line.text+"\n")fp.write("\n\n")print(f"{title}爬取成功")
fp.close()

效果:

2fed6d19354c427799d07f88da4f0cb3.png

3.3 xpath解析

最常用且是最便捷高效的一种解析方式

3.3.1 xpath解析原理

  • 实例化一个etree的对象,且将被解析的页面远吗数据加载到该对象中
  • 调用etree对象中的xpath方法结合xpath表达式实现标签的定位和内容的捕获

3.3.2 环境的安装

pip3 install lxml  -i  https://mirrors.aliyun.com/pypi/simple

3.3.3 具体使用

xpath只能够根据层级关系定位标签页面.

1d80a29970ae42d885f98586b60dd8f9.png

ba9263465f7742479051cd9574f5c8fd.png

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<!--    <meta charset="UTF-8">-->
<!--    <meta name="viewport" content="width=device-width, initial-scale=1.0">--><title>小型HTML页面示例</title>
</head>
<body><div class="container"><div class="div1"><h2>第一个Div</h2><p>这是第一个div的内容。它使用了类标签.div1进行样式定位。</p><p>这是第一个div的内容。它使用了类标签.div2进行样式定位。</p><p><title>这是第一个div的内容。它使用了类标签.div3进行样式定位。</title></p></div><div class="div2"><h2>第二个Div</h2><p>这是第二个div的内容。它使用了类标签.div2进行样式定位。</p></div><div class="div3"><h2 class="div3_h2">第三个Div</h2><p>这是第三个div的内容。它使用了类标签.div3进行样式定位。</p></div></div>
</body>
</html>
from lxml import etreetree_ = etree.parse("./baidu.html")
# r = tree_.xpath("/html/head/title")  # => [<Element title at 0x10a79ee60>],返回的是定位出来的对象
# r = tree_.xpath("/html//title")  # => [<Element title at 0x10a510dc0>],定位出来的效果是一样的
# r = tree_.xpath("//title") # => [<Element title at 0x106b75dc0>],找到源码里面所有的title标签# 属性定位
# r = tree_.xpath('//div[@class="div1"]') # => [<Element div at 0x101807e60>]# 索引定位,索引位置从1开始
# r = tree_.xpath('//div[@class="div1"]/p[3]')# 取文本 /text()获取的标签里面直系的文本内容, //text() 获取标签下面所有的文本内容
# text = tree_.xpath('//div[@class="div1"]/p[3]/text()')
# print(text)  # => ['这是第一个div的内容。它使用了类标签.div3进行样式定位。']
# text = tree_.xpath('//div[@class="div1"]//text()')
# print(text)# 获取属性
# attr = tree_.xpath('//div[@class="div3"]/h2/@class')  # ['div3_h2']
# print(attr)

3.3.4 爬取ppt模板

已经成功,结果如下,但是是大学时多亏了它的免费模板,就不贴代码给它带来麻烦了

99221c29b8094f67b7b8f70744dd24fa.png

3.3.5 爬取美女图片

https://pic.netbian.com/4kmeinv/

爬取美女图片失败,开始进入网站总是有人机验证,进去什么都爬取不了,后面再试一下

db1321caf5304010a2a3d806cc43f60c.png

4.模拟登录

4.1 验证码识别 

要收费,自己写个图片文字识别

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/12/28 13:44
# @Author : George
from PIL import Image
import pytesseract# 如果你没有将tesseract.exe添加到系统的PATH中,
# 你需要在这里指定tesseract可执行文件的完整路径
pytesseract.pytesseract.tesseract_cmd = r'D:\Tesseract-OCR\tesseract.exe'# 打开一个图像文件
image_path = 'abc_1.png'  # 替换为你的图像路径
image = Image.open(image_path)# 使用pytesseract进行OCR
text = pytesseract.image_to_string(image, lang='chi_sim')  # lang参数指定语言,例如'chi_sim'表示简体中文# 打印识别出的文字
print(text)

4.2 模拟登录逻辑

5.cookie

5.1含义及作用

网页的Cookie是一种在Web开发中广泛使用的技术,用于在用户的计算机上存储小块的数据。这些数据通常由Web服务器发送给用户的浏览器(所以主要是服务器创建的),并在用户后续的访问中被浏览器返回给服务器。Cookie的主要功能和用途包括:

  1. 会话管理:Cookie可以用于保持用户的会话状态,例如在用户登录到网站后,服务器可以发送一个包含会话ID的Cookie到用户的浏览器。在用户后续的请求中,浏览器会自动包含这个会话ID,使得服务器能够识别并持续管理用户的会话。

  2. 个性化设置:Cookie可以用来存储用户的偏好设置,例如网站的语言、主题颜色、字体大小等。这样,当用户再次访问网站时,这些设置可以自动恢复,提高用户体验。

  3. 跟踪用户行为:通过Cookie,网站可以跟踪和分析用户的行为,例如用户访问了哪些页面、停留了多长时间、点击了哪些链接等。这些信息对于网站优化、广告定位等非常有用。

  4. 安全性:在某些情况下,Cookie还可以用于增强网站的安全性,例如通过存储加密的令牌来验证用户的身份。

Cookie具有以下几个特点:

  • 存储在客户端:Cookie数据存储在用户的浏览器上,而不是服务器上。这意味着即使用户关闭了浏览器或计算机,只要没有删除Cookie,数据仍然存在。
  • 自动发送:在用户访问与Cookie相关的网站时,浏览器会自动将相关的Cookie数据发送到服务器。
  • 有限的大小和数量:每个Cookie的大小和数量都有限制,这取决于浏览器和Web服务器的配置。
  • 过期时间:Cookie可以设置过期时间,在过期时间之前,Cookie一直有效。如果没有设置过期时间,Cookie就是一个会话Cookie,在用户关闭浏览器时自动删除。

5.2 session的含义及特点

  • 一、Session的基本概念

Session是服务器用于跟踪用户会话的一种机制。它允许服务器在多个请求之间识别同一个用户,并维护该用户的状态信息。这些状态信息可以包括用户的登录状态、购物车内容、偏好设置等。

  • 二、Session的工作原理
  1. 创建Session:当用户首次访问网站时,服务器会创建一个新的Session对象,并为其分配一个唯一的Session ID。
  2. 发送Session ID:服务器通常会将这个Session ID以Cookie的形式发送给客户端浏览器。客户端浏览器会在后续的请求中自动将这个Session ID附加在请求头中。
  3. 识别用户:服务器通过检查请求头中的Session ID来识别用户,并获取相应的Session数据。这样,服务器就可以在多个请求之间保持用户的状态信息。
  • 三、Session的作用
  1. 保持用户状态:Session允许服务器在多个请求之间跟踪用户的状态信息,如登录状态、购物车内容等。这使得用户可以在不同页面之间无缝切换,而无需重新认证或输入信息。
  2. 个性化服务:根据用户的喜好和历史行为,服务器可以为用户提供个性化的内容和服务。这有助于提高用户体验和满意度。
  3. 安全性:通过验证Session ID来确认用户的请求,服务器可以防止未授权访问和非法操作。这有助于保护用户的隐私和数据安全。
  • 四、Session与Cookie的关系

Session和Cookie是密切相关的两种技术。Cookie是服务器发送到客户端浏览器并保存在本地的一小块数据,而Session则是服务器用于跟踪用户会话的一种机制。Cookie通常用于存储Session ID,以便服务器在后续的请求中识别用户。因此,可以说Cookie是Session的一种实现方式。

  • 五、Session的管理

在网络请求中,管理Session是非常重要的。开发人员需要确保Session的安全性、有效性和可维护性。这包括:

  1. 设置合理的Session过期时间:为了避免用户长时间未操作而导致的会话过期问题,开发人员需要设置合理的Session过期时间。
  2. 保护Session ID:Session ID是用户身份的重要标识,开发人员需要采取措施来保护它免受攻击和泄露。例如,可以使用HTTPS协议来加密传输Session ID,或者使用更复杂的Session ID生成算法来提高安全性。
  3. 清理无效的Session:为了节省服务器资源和提高性能,开发人员需要定期清理无效的Session对象。这可以通过设置Session的失效时间、使用数据库存储Session数据并定期清理过期数据等方式来实现。

5.3 http和https协议的特点

无状态。即是说,即使你的第一次请求已经实现了自动登录。但是你第二次发送请求时,服务器端并不知道你的请求是基于第一次登录状态的。

cookie可以让服务器端记录客户端的相关状态

5.3 cookie值的处理

  • 手动抓包cookie值,将其封装到headers里面,但是这种方法面对cookie是动态变化的时候就很难处理了
  • session会话对象
    • 可以进行请求的发送
    • 如果请求过程中产生了cookie,则该cookie会被自动存储/携带在该session会话对象中
  • b3b252aa2fe644b3aef552a0ef159520.png

6.代理

需要绕过IP封锁、限制或进行大规模数据抓取时。代理服务器充当客户端和目标服务器之间的中介,可以隐藏你的真实IP地址,提供额外的安全性,有时还能加速请求

测试网址:

https://httpbin.org/get

现在基本上没有免费正常的代理可以被使用,我这个也是失败的。看到一个博主写建立代理ip池的python3之爬虫代理IP的使用+建立代理IP池_python爬虫代理池-CSDN博客,代码写的不错,爬取出来的ip也没什么能用的了。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/12/28 19:14
# @Author : George
import requestsurl = "https://www.baidu.com/s?"# 将爬虫程序伪装成为浏览器来发送请求
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
}# 设置代理
proxies = {"http": "154.203.132.49:8080","https":"49.73.4.158:8089"
}
param = {"wd":"ip"
}response = requests.get(url,headers=headers,proxies=proxies,verify=False,params=param)
with open("proxy.html","wt",encoding="utf-8") as f:f.write(response.text)

公司的联网也是需要代理的

# _*_ coding utf-8 _*_
# george
# time: 2024/12/24下午7:56
# name: test.py
# comment:
import requestsuser = ""
passwd = "url = "https://www.baidu.com/"# 模拟浏览器
header = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
}
# 指定代理,不指定代理,无法上网
proxies = {"http": f"http://{user}:{passwd}@ip:port","https": f"https://{user}:{passwd}@ip:port"
}# 获取响应对象
response = requests.get(url, headers=header, proxies=proxies)# 获取响应内容,可以通过response.text获取字符串形式的响应数据
page_text = response.content# 持久化储存
with open("baidu.html", "wb") as f:f.write(page_text)

7.异步爬虫(进程池)

本来是针对视频进行爬取的,但是ajax请求时的请求地址,看不懂mrd这个怎么来的,暂时跳过,我灰太狼一定会回来的!!!!!!!!!!!!

295b11c4eb6346fba989e6cdf2874352.png

d684c278cec246cf8b9eb62f1497660d.png

7.1 视频爬取

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/12/29 13:16
# @Author : George
import requests
import chardet
import os
from lxml import etree
"""
"https://www.pearvideo.com/category_1"
['video_1797596', 'video_1797399', 'video_1797404', 'video_1797260']https://www.pearvideo.com/video_1797596ajax请求
https://www.pearvideo.com/videoStatus.jsp?contId=1797596&mrd=0.4308675768914054
https://www.pearvideo.com/videoStatus.jsp?contId=1797399&mrd=0.6241695396585363
"""class LiVideo(object):def __init__(self):#  定义输出ppt的文件夹self.extract_to_dir = f"./video"os.makedirs("./video", exist_ok=True)# 添加Referer防止反爬虫self.header = {"Referer": "https://www.pearvideo.com/","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"}# 编码self.encoding = Noneself.home_url = "https://www.pearvideo.com/category_1"def get_HTML(self, url_param):response = requests.get(url_param, headers=self.header)if response.status_code == 200:# 使用 chardet 自动检测编码self.encoding = chardet.detect(response.content)['encoding']response.encoding = self.encoding# 创建etree对象tree = etree.HTML(response.text)return treedef deal(self):home_tree = self.get_HTML(self.home_url)home_url_list = home_tree.xpath("//*[@id='listvideoListUl']/li/div/a[1]/@href")name_list = home_tree.xpath("//*[@id='listvideoListUl']/li/div/a[1]/div[2]/text()")for name,url in zip(name_list,home_url_list):url = "https://www.pearvideo.com/"+urldetail_tree = self.get_HTML(url)if __name__ == '__main__':vi = LiVideo()vi.deal()

 7.2 诗文异步爬取

只要将任务提交给线程池,线程池就会自动安排一个线程来执行这个任务.同过线程池提交的任务是异步提交.异步提交的结果就是不等待任务的执行结果,继续往下执行 

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/12/29 14:26
# @Author : George
"""
https://www.gushiwen.cn/guwen/Default.aspx?p=1&type=%e5%b0%8f%e8%af%b4%e5%ae%b6%e7%b1%bb第二层
https://www.gushiwen.cn/guwen/book_4e6b88d8a0bc.aspx
https://www.gushiwen.cn/guwen/book_a09880163008.aspx第三層
https://www.gushiwen.cn/guwen/bookv_b630af160f65.aspx
"""
import os
import requests
import chardet
from lxml import etree
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor
import time
from typing import Dict, List, Tupleclass NovelDownloader:def __init__(self):self.output_dir = "./novels"os.makedirs(self.output_dir, exist_ok=True)self.headers = {"Referer": "https://www.gushiwen.cn/guwen/Default.aspx?p=1","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"}self.base_url = "https://www.gushiwen.cn"self.home_url = f"{self.base_url}/guwen/Default.aspx?p=1&type=%e5%b0%8f%e8%af%b4%e5%ae%b6%e7%b1%bb"def get_html_tree(self, url: str) -> etree._Element:"""获取页面HTML并返回etree对象"""response = requests.get(url, headers=self.headers)if response.status_code != 200:raise Exception(f"Failed to get {url}, status code: {response.status_code}")encoding = chardet.detect(response.content)['encoding']response.encoding = encodingreturn etree.HTML(response.text)def get_chapter_details(self) -> Dict[str, Dict[str, str]]:"""获取所有章节详情"""home_tree = self.get_html_tree(self.home_url)# 获取书籍链接和标题urls = home_tree.xpath("//*[@class='sonspic']/div[1]/p[1]/a[1]/@href")[1:3]titles = home_tree.xpath("//*[@class='sonspic']/div[1]/p[1]/a[1]/b/text()")[1:3]book_details = {}for title, url in zip(titles, urls):detail_tree = self.get_html_tree(f"{self.base_url}{url}")# 获取章节链接和标题chapter_urls = [f"{self.base_url}{url}" for url in detail_tree.xpath("//*[@class='bookcont']/ul/span/a/@href")]chapter_titles = detail_tree.xpath("//*[@class='bookcont']/ul/span/a/text()")book_details[title] = dict(zip(chapter_titles, chapter_urls))return book_detailsdef download_novel(self, title: str, chapters: Dict[str, str]):"""下载单本小说"""output_path = os.path.join(self.output_dir, f"{title}.txt")print(f"开始下载 {title}".center(100, "="))with open(output_path, "w", encoding="utf-8") as f:for chapter_title, chapter_url in chapters.items():response = requests.get(chapter_url, headers=self.headers)soup = BeautifulSoup(response.text, "lxml")f.write(f"{chapter_title}:\n")for paragraph in soup.select('.contson > p'):f.write(f"{paragraph.text}\n")f.write("\n\n")print(f"{chapter_title} 下载完成".center(20, "-"))print(f"{title} 下载完成".center(100, "="))def main():start_time = time.time()downloader = NovelDownloader()books = downloader.get_chapter_details()# 使用线程池并行下载with ThreadPoolExecutor(max_workers=10) as pool:futures = [pool.submit(downloader.download_novel, title, chapters) for title, chapters in books.items()]print(f"总耗时: {time.time() - start_time:.2f}秒")if __name__ == '__main__':main()

8.异步爬虫(协程)

  协程内容不赘述:CSDN

c62484262bf6460187337af4d2ab3996.png

基于单线程和协程,实现异步爬虫。 

8.1. 基于flask搭建服务器

简单的学习了一下,感觉不是很复杂,后面等着详细学习

261a05e6ee984879838d6b8015f8b299.png

pip3 install Flask -i  https://mirrors.aliyun.com/pypi/simple
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/12/31 21:47
# @Author : George
"""
# @app.route('/'): 这是一个装饰器,用于告诉 Flask 哪个 URL 应该触发下面的函数。
在这个例子中,它指定了根 URL(即网站的主页)。# return 'Hello, World!': 这行代码是 hello_world 函数的返回值。
当用户访问根 URL 时,这个字符串将被发送回用户的浏览器。"""
from flask import Flask, request, jsonify
import timedef get_client_ip(request):# 如果使用了反向代理,优先从 X-Forwarded-For 头部获取 IP 地址x_forwarded_for = request.headers.get('X-Forwarded-For', '').split(',')if x_forwarded_for:client_ip = x_forwarded_for[0]  # 通常第一个 IP 地址是客户端的真实 IP 地址else:client_ip = request.remote_addrreturn client_ipapp = Flask(__name__)@app.route('/')
def index():return 'Hello, World!'@app.route('/bobo')
def index_bobo():# 获取client的user_agent和refereruser_agent = request.headers.get('User-Agent')user_referer = request.headers.get('Referer')print(user_agent, user_referer)# client ip地址没有获取到client_ip = get_client_ip(request)print({'client_ip': client_ip})time.sleep(3)return 'bobo'@app.route('/jar')
def index_jar():time.sleep(3)return 'jar'@app.route('/test')
def index_test():time.sleep(3)return 'test'if __name__ == '__main__':app.run(threaded=True)

8.2 基于aiohttp实现异步爬虫

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/12/31 22:08
# @Author : George
import asyncio
import requests
import time
import aiohttp
from threading import currentThread"""
async def request(url): # 耗时: 9.054526805877686,requests是同步阻塞,必须替换为异步库提供的函数aiohttp
"""urls = ["http://127.0.0.1:5000/jar","http://127.0.0.1:5000/bobo","http://127.0.0.1:5000/test"
]start = time.time()# 耗时: 9.054526805877686,requests是同步操作
# async def request(url):
#     print("开始下载", url)
#     response = requests.get(url=url)
#     print(response.text)
#     print("下载结束", url)
#     print("------------")async def request_2(url):print("开始下载", url, currentThread())headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36","Referer": "https://movie.douban.com/explore"}# 设置代理proxy = "http://8.220.204.215:8008"async with aiohttp.ClientSession() as session:async with session.get(url, headers=headers) as response:text = await response.text()print(text)print("下载结束", url)async def main():tasks = []for url in urls:tasks.append(asyncio.create_task(request_2(url)))await asyncio.wait(tasks)asyncio.run(main())end = time.time()
print("耗时:", end - start)

9.selenuim使用

  • 便捷的获取网页中间动态加载的数据
  • 边界实现模拟登录

selenuim:基于浏览器自动化的一个模块

入门指南 | Selenium

b2505f3011124e5bb0606b9d5922d52f.png

基于selenium实现浏览器自动化,自动输入并播放动漫核心代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/1/1 16:04
# @Author : George
"""
在 Selenium 4 中,不再直接在 webself.driver.Chrome 中设置驱动程序路径,而是通过引入 Service 对象来设置。
这样可以避免弃用警告,并确保驱动程序的正确加载
"""
import os.pathfrom selenium import webdriver
from selenium.webdriver.edge.service import Service as EdgeService
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import time
from lxml import etree
import requests
import chardet
import json
from log_test import loggerclass VideoAutoPlay(object):def __init__(self):self.driver = {}self.count_num = 1self.movies_dict =Noneself.home_url = "https://www.agedm.org/"self.headers = {"Referer": "https://www.agedm.org/","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"}def get_html_tree(self, url: str) -> etree._Element:"""获取页面HTML并返回etree对象"""response = requests.get(url, headers=self.headers)if response.status_code != 200:raise Exception(f"Failed to get {url}, status code: {response.status_code}")encoding = chardet.detect(response.content)['encoding']response.encoding = encodingreturn etree.HTML(response.text)def movies_input(self, movie_name, n):try:if not self.driver:self.driver = self.setup_driver()self.driver.get(self.home_url)# 查找搜索框元素search_box = self.driver.find_element(By.ID, "query")# 输入搜索内容search_box.send_keys(movie_name)# 提交搜索表单search_box.send_keys(Keys.RETURN)# 等待搜索结果加载# WebDriverWait(self.driver, 10).until(#     EC.presence_of_element_located((By.CLASS_NAME, "content_left"))# )# 二级请求self.driver.get(f"https://www.agedm.org/search?query={movie_name}")# 查找在线播放btn# wait = WebDriverWait(self.driver, 10)  # 10秒超时# # titles = home_tree.xpath("//*[@class='sonspic']/div[1]/p[1]/a[1]/b/text()")button = self.driver.find_element(By.XPATH, "//*[@class='video_btns']/a[1]")# print(button)button.click()WebDriverWait(self.driver, 30).until(EC.presence_of_element_located((By.CLASS_NAME, "tab-content")))# # 等待搜索结果加载detail_url = self.driver.current_urltree = self.get_html_tree(detail_url)url_dict = {}titles = tree.xpath("//*[@class='video_detail_episode']/li/a/text()")[n - 1:]urls = tree.xpath("//*[@class='video_detail_episode']/li/a/@href")[n - 1:]for title, url in zip(titles, urls):url_dict[title] = url# print(url_dict)return url_dictexcept Exception as e:logger.error(f"搜索过程发生错误: {str(e)}")if self.driver:self.driver.quit()self.driver = Nonereturn {}def setup_driver(self):# 优化视频播放性能的设置options = webdriver.EdgeOptions()options.add_argument('--disable-gpu')  # 禁用GPU加速options.add_argument('--no-sandbox')  # 禁用沙箱模式options.add_argument('--disable-dev-shm-usage')  # 禁用/dev/shm使用options.add_argument('--disable-software-rasterizer')  # 禁用软件光栅化options.add_argument('--disable-extensions')  # 禁用扩展options.add_argument('--disable-infobars')  # 禁用信息栏options.add_argument('--autoplay-policy=no-user-gesture-required')  # 允许自动播放options.add_experimental_option('excludeSwitches', ['enable-automation'])  # 禁用自动化提示options.add_experimental_option("useAutomationExtension", False)  # 禁用自动化扩展# 设置正确的驱动路径service = EdgeService(executable_path='./msedgedriver.exe')return webdriver.Edge(options=options, service=service)def video_player(self, movie_name, n):try:url_dict = self.movies_input(movie_name, n)if not url_dict:logger.error("未找到可播放的视频链接")returnif not self.driver:self.driver = self.setup_driver()for title, url in url_dict.items():try:# 打开网站self.driver.get(url)# 切换到视频iframeself.driver.switch_to.frame("iframeForVideo")logger.info(f"开始时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}")# 等待视频元素加载wait = WebDriverWait(self.driver, 20)video_element = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "art-video")))logger.info(f"找到视频元素: {video_element}")logger.info(f"{movie_name}:{title}集开始播放".center(10, "="))# 等待视频加载完成后执行全屏page_stage = Truewhile page_stage:paused_state = self.driver.execute_script("return arguments[0].paused;", video_element)print("paused_state", paused_state)if not paused_state:break# 双击使得视频全屏显示ActionChains(self.driver).double_click(video_element).perform()time.sleep(3)# 视频单击播放paused_state = self.driver.execute_script("return arguments[0].paused;", video_element)if paused_state:logger.info(f"{movie_name}:{title}触发双击全屏")ActionChains(self.driver).click(video_element).perform()# # 点击视频开始播放# action = ActionChains(self.driver)# action.move_to_element_with_offset(video_element, 100, 100).click().perform()print(f"点击播放时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}")# 等待视频播放完成time.sleep(60*21)n = n + 1self.update_movie_count(movie_name,n)logger.info(f"第{title}集播放完毕".center(10, "="))except Exception as e:logger.error(f"播放第{title}集时发生错误: {str(e)}")continueexcept Exception as e:logger.error(f"视频播放总体发生错误: {str(e)}")finally:if self.driver:self.driver.quit()self.driver = Nonedef __del__(self):"""确保在对象销毁时关闭driver"""if self.driver:try:self.driver.quit()except:passdef count_read(self, movies, n=1):# 将此文件作为播放内容的缓存if not os.path.exists("./count.json"):with open("./count.json", "w", encoding="utf-8") as f:self.movies_dict = {movies:n}json.dump({movies: n}, f, ensure_ascii=False, indent=4)return nelse:with open("./count.json", "r", encoding="utf-8") as f:self.movies_dict = json.load(f)if not self.movies_dict.get(str(movies)):  # 读取不到moviesself.movies_dict.update({str(movies):n})with open("./count.json", "w", encoding="utf-8") as f:json.dump(self.movies_dict, f, ensure_ascii=False, indent=4)return nelse:  # 读取到了movieself.count_num = self.movies_dict[str(movies)]return self.count_num# update movies countdef update_movie_count(self, movies, n):with open("./count.json", "w", encoding="utf-8") as f:self.movies_dict[str(movies)] = njson.dump(self.movies_dict, f, ensure_ascii=False, indent=4)if __name__ == "__main__":video = VideoAutoPlay()movie = "火影忍者 疾风传"# movie = "神之塔 第二季"count_num = video.count_read(movie, 1)# video.update_movie_count(movie, 4)video.video_player(movie, count_num)

10.scrapy框架

破电脑太老,安装不了!!

d684c278cec246cf8b9eb62f1497660d.png

相关文章:

爬虫学习记录

1.概念 通过编写程序,模拟浏览器上网,然后让其去互联网上抓取数据的过程 通用爬虫:抓取的是一整张页面数据聚焦爬虫:抓取的是页面中的特定局部内容增量式爬虫:监测网站中数据更新的情况,只会抓取网站中最新更新出来的数据 robots.txt协议: 君子协议,网站后面添加robotx.txt…...

Erlang语言的函数实现

Erlang语言函数实现的深度探讨 引言 Erlang是一种并发编程语言&#xff0c;最初由爱立信公司为电信系统开发。它以其强大的并发处理能力和容错机制而闻名&#xff0c;广泛应用于实时系统和分布式系统。本文将详细探讨Erlang语言中的函数实现&#xff0c;包括函数的定义、调用…...

LLM之RAG实战(五十一)| 使用python和Cypher解析PDF数据,并加载到Neo4j数据库

一、必备条件&#xff1a; python语言Neo4j数据库python库&#xff1a;neo4j、llmsherpa、glob、dotenv 二、代码&#xff1a; from llmsherpa.readers import LayoutPDFReaderfrom neo4j import GraphDatabaseimport uuidimport hashlibimport osimport globfrom datetime …...

单例模式-如何保证全局唯一性?

以下是几种实现单例模式并保证全局唯一性的方法&#xff1a; 1. 饿汉式单例模式 class Singleton { private:// 私有构造函数&#xff0c;防止外部创建对象Singleton() {}// 静态成员变量&#xff0c;存储单例对象static Singleton instance; public:// 公有静态成员函数&…...

05、Docker学习,常用安装:Mysql、Redis、Nginx、Nacos

Docker学习&#xff0c;常用安装&#xff1a;Mysql、Redis、Nginx、Nacos 一、Docker安装Mysql 1、docker search mysql ##查找mysql版本都有哪些 2、docker pull mysql:5.6 ##下载5.6版本的mysql镜像 3、docker run -p 13306:3306 --name mysql ##运行…...

docker 启动redis 守护进程

文章目录 前言一、整体流程二、状态图三、结语 前言 在现代软件开发中&#xff0c;缓存和消息队列是提高应用性能和扩展性的关键。Redis 是一种流行的内存数据结构存储系统&#xff0c;它支持多种类型的数据结构&#xff0c;如字符串、哈希、列表、集合、有序集合等。使用 Doc…...

Angular由一个bug说起之十三:Cross Origin

跨域 想要了解跨域&#xff0c;首要要了解源 什么是源&#xff0c;源等于协议加域名加端口号 只有这三个都相同&#xff0c;才是同源&#xff0c;反之则是非同源。 比如下面这四个里&#xff0c;只有第4个是同源 而浏览器给服务器发送请求时&#xff0c;他们的源一样&#xff0…...

为深度学习引入张量

为深度学习引入张量 什么是张量&#xff1f; 神经网络中的输入、输出和转换都是使用张量表示的&#xff0c;因此&#xff0c;神经网络编程大量使用张量。 张量是神经网络使用的主要数据结构。 张量的概念是其他更具体概念的数学概括。让我们看看一些张量的具体实例。 张量…...

opencv摄像头标定程序实现

摄像头标定是计算机视觉中的一个重要步骤&#xff0c;用于确定摄像头的内参&#xff08;如焦距、主点、畸变系数等&#xff09;和外参&#xff08;如旋转矩阵和平移向量&#xff09;。OpenCV 提供了方便的工具来进行摄像头标定。下面分别给出 C 和 Python 的实现。 1. C 实现…...

Flutter:封装一个自用的bottom_picker选择器

效果图&#xff1a;单列选择器 使用bottom_picker: ^2.9.0实现&#xff0c;单列选择器&#xff0c;官方文档 pubspec.yaml # 底部选择 bottom_picker: ^2.9.0picker_utils.dart AppTheme&#xff1a;自定义的颜色 TextWidget.body Text() <Widget>[].toRow Row()下边代…...

Docker 容器自动化管理之脚本(Script for Docker Container Automation Management)

Docker 容器自动化管理之脚本 简介 Docker‌是一个开源的容器化平台&#xff0c;旨在简化应用程序的开发、部署和运行过程。它通过将应用程序及其依赖项打包到一个可移植的容器中&#xff0c;使得开发人员能够在不同的环境中以一致的方式构建、打包和分发应用程序‌。 Docke…...

client-go中watch机制的一些陷阱

Reference https://stackoverflow.com/questions/51399407/watch-in-k8s-golang-api-watches-and-get-events-but-after-sometime-doesnt-get-an 问题描述 最近在使用 client-go 的 watch 机制监听 k8s 中的 deployment 资源时&#xff0c;发现一个奇怪的现象 先看下代码&a…...

用户界面的UML建模11

然而&#xff0c;在用户界面方面&#xff0c;重要的是要了解《boundary》类是如何与这个异常分层结构进行关联的。 《exception》类的对象可以作为《control》类的对象。因此&#xff0c;《exception》类能够聚合《boundary》类。 参见图12&#xff0c;《exception》Database…...

计算机网络之---数据链路层的功能与作用

数据链路层概念 数据链路层&#xff08;Data Link Layer&#xff09;是计算机网络中的第二层&#xff0c;它位于物理层和网络层之间&#xff0c;主要负责数据在物理链路上的可靠传输。其基本功能是将网络层传来的数据分成帧&#xff0c;并负责在物理链路上可靠地传输这些数据帧…...

添加到 PATH 环境变量中

命令解释 # 将命令中的<CLI_PATH>替换为您aliyun文件的所在目录。 echo export PATH$PATH:<CLI_PATH> >> ~/.bash_profile echo export PATH$PATH:/data2/ljsang/aliyun/aliyun >> ~/.bash_profileexport PATH$PATH:/data2/ljsang/aliyun/aliyun&…...

【51单片机零基础-chapter6:LCD1602调试工具】

实验0-用显示屏LCD验证自己的猜想 如同c的cout,前端的console.log() #include <REGX52.H> #include <INTRINS.H> #include "LCD1602.h" int var0; void main() {LCD_Init();LCD_ShowNum(1,1,var211,5);while(1){;} }实验1-编写LCD1602液晶显示屏驱动函…...

Linux 内核中的 netif_start_queue 函数:启动网络接口发送队列的关键

在 Linux 内核的网络子系统中,netif_start_queue 函数扮演着至关重要的角色。这个函数的主要功能是启动(或启用)网络接口的发送队列,标志着网络接口已经准备好开始发送数据包。本文将深入探讨 netif_start_queue 函数的用途、工作原理以及在实际网络驱动代码中的应用。 函…...

(七)人工智能进阶之人脸识别:从刷脸支付到智能安防的奥秘,小白都可以入手的MTCNN+Arcface网络

零、开篇趣谈 还记得第一次用支付宝"刷脸"时的新奇感吗&#xff1f;或者被抖音的人脸特效逗乐的瞬间&#xff1f;这些有趣的应用背后&#xff0c;其实藏着一个精妙的AI世界。今天&#xff0c;就让我们开启一段奇妙的人脸识别技术探索之旅吧&#xff01; 一、人脸识…...

ExcelDataReader:一个.Net高性能Excel开源读取器

推荐一个用于读取Microsoft Excel文件的高性能开源库。 01 项目简介 ExcelDataReader是一个功能强大且易于使用的开源项目&#xff0c;提供了丰富的读取API&#xff0c;专门读取Excel文件的数据&#xff0c;特别是处理大数据量的情况。 ExcelDataReader支持Excel版本从2007年…...

人工智能-机器学习之多元线性回归(项目实践一)

目标&#xff1a;运用scikit-learn进行多元线性回归方程的构建&#xff0c;通过实际案例的训练集和测试集进行预测&#xff0c;最终通过预测结果和MSE来评估预测的精度。 一、首先安装scikit-learn&#xff1a;pip install scikit-learn C:\Users\CMCC\PycharmProjects\AiPro…...

Mysql--基础篇--约束(主键,外键,唯一,检查,枚举及复合约束等)

在MySQL中&#xff0c;约束&#xff08;Constraints&#xff09;是用于确保数据库中数据完整性和一致性的规则。通过定义约束&#xff0c;可以防止用户插入、更新或删除不符合特定条件的数据&#xff0c;从而保证数据的准确性和可靠性。MySQL支持多种类型的约束&#xff0c;每种…...

经典多模态模型CLIP - 直观且详尽的解释

对比语言-图像预训练&#xff08;CLIP&#xff09;&#xff0c;这是一种创新的多模态建模策略&#xff0c;能够创建视觉和语言的联合表示。CLIP 的效果非常出色&#xff0c;可以用于构建高度特定且性能卓越的分类器&#xff0c;而无需任何训练数据。本文将深入探讨其理论基础&a…...

着丝粒鉴定CentIER v3.0安装与使用-bioinfomatics tools41

使用CentIE鉴定着丝粒 T2T基因组端粒与着丝粒的区别及其鉴定方法-随笔02_chip-seq鉴定着丝粒-CSDN博客 T2T时代的基因组组装-文献精读-9_基因组t2t组装-CSDN博客 桑树T2T基因组-文献精读16_桑树基因组-CSDN博客 辣椒属2个T2T基因组-文献精读23_辣椒基因组-CSDN博客 大花…...

Objective-C语言的多线程编程

Objective-C语言的多线程编程 在现代应用程序开发中&#xff0c;尤其是移动应用开发&#xff0c;多线程编程是一个不可或缺的部分。使用多线程可以提升应用的响应能力&#xff0c;使得可以同时处理多个任务&#xff0c;从而优化用户体验。在本文中&#xff0c;我们将深入探讨O…...

Golang的并发编程框架比较

# Golang的并发编程框架比较 中的并发编程 在现代软件开发中&#xff0c;处理高并发的能力愈发重要。Golang作为一门支持并发编程的编程语言&#xff0c;提供了丰富的并发编程框架和工具&#xff0c;使得开发者能够更轻松地处理并发任务。本文将介绍Golang中几种常用的并发编程…...

通过 oh-my-posh posh-git 优化PowerShell

转自oh-my-posh & posh-git 提升在 windows 环境的开发体验 oh-my-posh 是用于自定义 PowerShell 主题和配色的工具&#xff0c;posh-git 则是为 PowerShell 提供了方便的 git 状态显示和命令补全功能。 安装PowerShell 7和 winget下载器&#xff0c;都可以直接在 Microsof…...

【Linux系列】Vim 编辑器中的高效文本编辑技巧:删除操作

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

慧集通(DataLinkX)iPaaS集成平台-连接器

如何创建连接器&#xff1f; 连接器是用于跟各系统进行连接&#xff0c;是集成交互的基础构成也是主要构成之一&#xff1b;连接器一般是根据业务系统的开放的不同方式由开发人员进行封装&#xff0c;封装完成后交付人员可以在所有连接那里建立对应的连接&#xff0c;连接需要…...

vue3使用vue3-video-play播放m3u8视频

1.安装vue3-video-play npm install vue3-video-play --save2.在组件中使用 import vue3-video-play/dist/style.css; import VideoPlay from vue3-video-play;// 视频配置项 const options reactive({src: https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8, //视频源mute…...

单片机-外部中断

中断是指 CPU 在处理某一事件 A 时&#xff0c;发生了另一事件 B&#xff0c;请求 CPU 迅速去处理(中断发生)&#xff1b;CPU 暂时停止当前的工作(中断响应)&#xff0c; 转去处理事件 B(中断服务)&#xff1b;待 CPU 将事件 B 处理完毕后&#xff0c;再回到原来事件 A 被中断的…...

《C++11》右值引用深度解析:性能优化的秘密武器

C11引入了一个新的概念——右值引用&#xff0c;这是一个相当深奥且重要的概念。为了理解右值引用&#xff0c;我们需要先理解左值和右值的概念&#xff0c;然后再理解左值引用和右值引用。本文将详细解析这些概念&#xff0c;并通过实例进行说明&#xff0c;以揭示右值引用如何…...

【HTML+CSS+JS+VUE】web前端教程-1-VScode开发者工具快捷键

VScode打开文件夹与创建文件 1、选择文件夹 2、拖拽文件夹 生成浏览器文件.html的快捷方式 ! 回车vscode常用快捷键列表 代码格式化&#xff1a;shift alt F 向上或向下移动一行&#xff1a; alt up 或者 alt down 快速复制一行代码&#xff1a;shift alt up 或者 sh…...

【嵌入式硬件】直流电机驱动相关

项目场景&#xff1a; 驱动履带车&#xff08;双直流电机&#xff09;前进、后退、转弯 问题描述 电机驱动MOS管烧毁 电机驱动采用IR2104STRH1R403NL的H桥方案&#xff08;这是修改之后的图&#xff09; 原因分析&#xff1a; 1.主要原因是4路PWM没有限幅&#xff0c;修改…...

接口测试-postman(使用postman测试接口笔记)

一、设置全局变量 1. 点击右上角设置按钮-》打开管理环境窗口-》选择”全局“-》设置变量名称&#xff0c;初始值和当前值设置一样的&#xff0c;放host放拼接的url&#xff0c;key放鉴权那一串字符&#xff0c;然后保存-》去使用全局变量&#xff0c;用{{变量名称}}形式 二、…...

强化学习常用库的版本对应关系

本文介绍了pytorch强化学习框架和常用python库的对应关系。 持续更新中! 基础包 工具包版本描述python3.9.13-numpy1.24.3-protobuf3.19.6结构化数据包cython0.29.21静态编译器setuptools66.0.0-学习框架 工...

Unity 热更新基础知识

文章目录 1.一些名词2.三种编译方式3.Unity 两种脚本后端3.1 Mono3.2 IL2CPP3.3 对比 1.一些名词 IL&#xff08;Intermediate Language&#xff09;&#xff1a;中间语言&#xff08;类似于汇编代码&#xff09;CIL&#xff08;Common Intermediate Language&#xff09;&…...

JetBrains IDEs和Visual Studio Code的对比

JetBrains IDEs和Visual Studio Code的对比 JetBrains IDEs是捷克JetBrains公司开发的一系列集成开发环境(IDE)。以下是具体介绍:IntelliJ IDEA是JetBrains 公司的一款产品 主要产品 IntelliJ IDEA:一款功能强大且广泛应用的Java集成开发环境,有开源免费的社区版和商业收…...

C语言将点分十进制的IP字符串转成4个整数

最近在做lldp的snmp返回值时需要做这样的转换处理&#xff1a;C语言将点分十进制的IP字符串转成4个整数。 这里用两种方式&#xff1a; sscanf格式化处理用 inet_aton函数将ip字符串转成32位的整形&#xff0c;然后再根据bit转成对应的4个整数。 man命令可以确认下sscanf和i…...

慧集通(DataLinkX)iPaaS集成平台:数据流程的基本操作

流程搭建与发布 该功能下是我们集成的流程配置实现&#xff0c;在这里我们可以通过搭建一条条不同的流程来实现不同的业务场景。列表界面如下所示&#xff1a; 下面我们做一个业务场景的流程来具体讲解下该功能&#xff08;OA销售单推送T销售出库单场景&#xff09;。 首先…...

三线结构光避障远近有度,石头自清洁扫拖机器人G30上市

1月8日&#xff0c;石头科技发布新一代自清洁扫拖机器人产品G30&#xff0c;以卓越的旗舰级性能&#xff0c;为用户带来了更为全面极致的清洁体验。在本届CES2025展会期间&#xff0c;石头G30现身石头科技展台&#xff0c;彰显极致清洁科技。 据「TMT星球」了解&#xff0c;石头…...

深入理解 React 中 setState 的行为及状态更新时机

在 React 开发中&#xff0c;setState 是我们更新组件状态的核心 API。然而&#xff0c;setState 的行为因调用场景的不同而有所变化&#xff0c;这可能会让许多开发者感到困惑。特别是在 React 18 中&#xff0c;引入了自动批量更新机制&#xff0c;使得部分场景的行为发生了变…...

一次完成Win10下MySQL 9.1 的安装

文章目录 前言一、 安装环境二、 安装方式选择三、下载四、安装 总结 前言 一、 安装环境 1、MySQL9.1.0.zip 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 2、Win10 3、客户端MySQL Workbench8.0 CE 下载地址&#xff1a;https://dev.mysql.com/downloads/w…...

有限元分析学习——Anasys Workbanch第一阶段笔记(8)水杯案例的对称与轴对称处理

目录 1 序言 2 对称处理 2.1 模型处理 2.2 网格划分、约束载荷及接触设置 2.3 计算结果 3 轴对称处理 3.1 对称与轴对称概念 3.2 轴对称问题的应用 3.2.1 创建分析案例 3.2.2 导入并处理模型 3.2.3 网格划分、约束载荷及接触设置 3.2.4 后处理计算结果 1 序言 本章…...

Vmware安装centos

用来记录自己安装的过程 一、创建虚拟机安装centos镜像 点击完成后&#xff0c;等待一会会进入centos的系统初始化界面 二、centos初始化配置 三、配置网络 1、虚拟网络编辑器&#xff0c;开启VMnet1、VMnet8的DHCP vmware左上角工具栏&#xff0c;点击【编辑】->【虚拟网…...

[Unity]MacOS下开发Unity

需要的插件 我使用的是vscode&#xff0c;经过长时间的使用我发现一个问题就是很多插件都是动态的在变化的&#xff0c;不是一成不变的&#xff0c;可能是重构&#xff0c;可能直接换了其他的工具。 所以这个插件也会是更新的状态。 2025年01月08日更新 .NET Install Tool …...

快手短剧播放器uniapp如何引入与对接?

uniApp前端微短剧项目开源分享 开源地址&#xff1a;git开源下载地址 文章目录 快手短剧播放器uniapp如何引入与对接&#xff1f;1.引入短剧播放器2.创建文件kscomponents组件3.local-stream.js文件说明4.用户行为事件4.local-stream.ksml文件参考如下 快手短剧播放器uniapp如何…...

Java 数据结构之-LinkedHashMap

继承关系和基本概念 LinkedHashMap是HashMap的子类&#xff0c;它继承了HashMap的基本功能。它在HashMap的基础上&#xff0c;通过维护一个双向链表来记录元素的插入顺序或者访问顺序&#xff08;可以通过构造函数指定&#xff09;&#xff0c;从而在遍历元素时能够按照特定的顺…...

记一次踩坑:json.Unmarshal() 解析数字类型

首先我们先明确下 json 包下 Unmarshal() 函数是什么&#xff1a; 它是 Go 语言标准库 encoding/json 中的一个函数&#xff0c;用于将 JSON 数据解析为 Go 语言中的数据结构。它的作用是将一个 JSON 格式的字节切片&#xff08;[]byte&#xff09;转换为对应的 Go 语言数据类…...

leetcode78.子集

给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2],[1,2],[3],…...

docker学习记录:创建mongodb副本集

目的&#xff0c;是创建三个&#xff0c;避免出现错误时&#xff0c;仍然能正常工作。 要在 Docker 中创建一个 MongoDB 集群&#xff08;副本集&#xff09;&#xff0c;并确保数据存储在本地&#xff0c;同时允许局域网访问&#xff0c;你可以按照以下步骤进行操作。我们将创…...