互联网中存在大量的边缘存储设备,MEMO通过对这种闲置资源的整合搭建了一个可扩展的分散式云存储协议,使存储资源有限的用户可将数据存储在边缘存储节点上。但是在这样一个公开的低可信环境中,边缘存储节点可靠性较低,他们可能会作出篡改、删除数据等恶意行为,因此需要对存储节点进行有效监督,以验证他们是否正确地持有存储数据。
2025年06月29日
互联网中存在大量的边缘存储设备,MEMO通过对这种闲置资源的整合搭建了一个可扩展的分散式云存储协议,使存储资源有限的用户可将数据存储在边缘存储节点上。但是在这样一个公开的低可信环境中,边缘存储节点可靠性较低,他们可能会作出篡改、删除数据等恶意行为,因此需要对存储节点进行有效监督,以验证他们是否正确地持有存储数据。
2025年06月29日
程派微信号:codingpy
本文为作者、kissg.me博主赵喧典授权编程派原创发布。文章比较长,大家可以收藏了慢慢看哈~~
引文
编程派前几天推送了一篇文章,叫“Python学习进阶路线(简版)”,生成器(generator)
赫然在列.可是我不太会.不会怎么办?学咯。于是上网看了不少教程,又看了官方文档,学到了不少知识。在此,权且做个学习笔记,也与大家分享一下。
2025年06月29日
1)说明:在 Python 中,这种一边循环一边计算的机制,称为生成器:generator。在 Python 中,使用了 yield 的函数被称为生成器(generator)。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值。并在下一次执行 next()方法时从当前位置继续运行。
2025年06月29日
# 导入所需库
import requests # 用于发送HTTP请求
import logging # 用于记录日志
import re # 用于正则表达式匹配
from urllib.parse import urljoin # 用于拼接URL
import json # 用于JSON数据处理
from os import makedirs # 创建目录
from os.path import exists # 检查路径是否存在
import multiprocessing # 用于多进程处理
# 基础URL和总页数常量
BASE_URL = 'https://ssr1.scrape.center' # 目标网站根URL
TOTAL_PAGE = 10 # 需要爬取的总页数
# 定义一个用于保存爬取结果的目录名,所有 JSON 文件将保存在这个文件夹中
RESULTS_DIR = 'results'
# 如果该目录不存在,则创建它(避免手动提前建目录)
# 使用短路逻辑:如果 exists(RESULTS_DIR) 为 False,就会执行 makedirs(RESULTS_DIR)
exists(RESULTS_DIR) or makedirs(RESULTS_DIR)
def save_data(data):
"""保存数据到JSON文件"""
name = data.get('name') # 从数据中获取电影名称作为文件名
data_path = f'{RESULTS_DIR}/{name}.json' # 构建文件路径
# 写入JSON文件(确保非ASCII字符正常显示)
json.dump(data, open(data_path, 'w', encoding='utf-8'),
ensure_ascii=False, indent=2)
# 配置日志格式和级别
logging.basicConfig(
level=logging.INFO, # 设置日志级别为INFO
format='%(asctime)s-%(levelname)s:%(message)s' # 日志格式:时间-级别-消息
)
def scrape_page(url):
"""通用页面爬取函数"""
logging.info('scraping %s...', url)
try:
response = requests.get(url) # 发送GET请求
if response.status_code == 200: # 如果响应成功
return response.text # 返回HTML内容
# 记录错误状态码
logging.error('get invalid status code %s while scraping %s',
response.status_code, url)
except requests.RequestException:
# 记录请求异常信息(包含堆栈跟踪)
logging.error('error occurred while scraping %s', url, exc_info=True)
def scrape_index(page):
"""列表页爬取函数"""
index_url = f'{BASE_URL}/page/{page}' # 构造列表页URL
return scrape_page(index_url) # 调用通用爬取方法
def parse_index(html):
"""解析列表页HTML,提取详情页URL"""
pattern = re.compile('<a.*?href="(.*?)".*?class="name">') # 匹配详情页链接的正则
items = re.findall(pattern, html) # 查找所有匹配项
if not items:
return [] # 无匹配返回空列表
for item in items:
detail_url = urljoin(BASE_URL, item) # 拼接完整URL
logging.info('get detail url %s', detail_url)
yield detail_url # 生成器逐个返回URL
def scrape_detail(url):
"""详情页爬取函数(直接复用通用爬取)"""
return scrape_page(url)
def parse_detail(html):
"""解析详情页HTML,提取电影信息"""
# 定义各类信息的正则表达式模式
cover_pattern = re.compile('class="item".*?<img.*?src="(.*?)".*?class="cover">', re.S)
name_pattern = re.compile('<h2.*?>(.*?)</h2>')
categories_pattern = re.compile('<button.*?category.*?<span>(.*?)</span>.*?</button>', re.S)
published_at_pattern = re.compile('(\d{4}-\d{2}-\d{2})\s?上映')
drama_pattern = re.compile('<div.*?drama.*?>.*?<p.*?>(.*?)</p>', re.S)
score_pattern = re.compile('<p.*?score.*?>(.*?)</p>', re.S)
# 提取并处理各项数据(处理可能的匹配失败)
cover = re.search(cover_pattern, html).group(1).strip() if re.search(cover_pattern, html) else None
name = re.search(name_pattern, html).group(1).strip() if re.search(name_pattern, html) else None
categories = re.findall(categories_pattern, html) if re.findall(categories_pattern, html) else []
published_at = re.search(published_at_pattern, html).group(1) if re.search(published_at_pattern, html) else None
drama = re.search(drama_pattern, html).group(1).strip() if re.search(drama_pattern, html) else None
score = float(re.search(score_pattern, html).group(1).strip()) if re.search(score_pattern, html) else None
# 返回结构化数据字典
return {
'cover': cover, # 封面图URL
'name': name, # 电影名称
'categories': categories, # 分类标签列表
'published_at': published_at, # 上映日期
'drama': drama, # 剧情简介
'score': score # 评分(浮点数)
}
def main(page):
"""主处理函数(单个页面的处理流程)"""
index_html = scrape_index(page) # 爬取列表页
detail_urls = parse_index(index_html) # 解析详情页URL
for detail_url in detail_urls:
detail_html = scrape_detail(detail_url) # 爬取详情页
data = parse_detail(detail_html) # 解析详情页数据
logging.info('get detail data %s', data)
logging.info('saving data to json data')
save_data(data) # 保存数据到文件
logging.info('data saved successfully')
if __name__ == '__main__':
"""多进程执行入口"""
pool = multiprocessing.Pool() # 创建进程池
pages = range(1, TOTAL_PAGE + 1) # 生成页码列表 (1-10)
pool.map(main, pages) # 多进程并行处理所有页面
pool.close() # 关闭进程池(停止添加新任务)
pool.join() # 等待所有子进程完成
2025年06月29日
2025年06月29日
通过前面的关于Python中进行函数式编程的系列文章的介绍,我们已经把函数式编程范式中的相关特性,以及Python内置的类、functools模块对函数式编程范式的支持,都介绍了一遍。
今天这篇文章,打算介绍一个支持Python更好地进行函数式编程的三方模块:funcy。
本文的主要内容有:
1、funcy模块的简单介绍
2、funcy中的三大件:map、filter和reduce