Python循环结合正则未正确向数组追加内容问题排查
问题描述
代码目标是从指定URL获取Linux内核RT补丁的版本号,遍历每个版本对应的sha256sums.asc页面,提取符合patch-.*?\.tar\.xz格式的文件名到数组patches_full_versions中。预期数组应包含2.6到6.9全版本的文件名,但实际仅保留了早期2.6版本的内容。已确认所有版本的sha256sums.asc文件都能成功获取,但数组未按预期填充完整,后续版本的文件名并未加入数组。
原代码
patches_versions = [] patches_full_versions = [] RT_PATCHES_BASE_URL = "https://cdn.kernel.org/pub/linux/kernel/projects/rt/" cleaner = re.compile("<.*?>") # For removing HTML tags later. # Create array of patches versions: patches_page_content = requests.get(RT_PATCHES_BASE_URL) patches_page_content.raise_for_status() stripped_content = re.sub(cleaner, "", patches_page_content.text) for line in stripped_content.splitlines(): x = False x = re.findall(r"[0-9]", line) if not line == "": if x: patches_versions.append(line.split("/")[0]) patch_name_pattern = re.compile(r'patch-.*?\.tar\.xz') for x in patches_versions: patch_version_page_content = requests.get(f"{RT_PATCHES_BASE_URL}{x}/sha256sums.asc") patch_version_page_content.raise_for_status() for match in re.findall(patch_name_pattern, patch_version_page_content.text): patches_full_versions.append(match)
问题排查与解决
1. 版本号提取逻辑错误
原代码提取版本号时,仅通过判断行内有数字就拆分取第一个元素,导致patches_versions数组混入了无效值(比如页面中带数字的非版本行),后续请求这些无效版本的URL时,即使返回200,文件内也没有符合模式的文件名,看起来像是循环“停止”了。
修复方案:用精准正则匹配版本目录格式(如2.6/、3.10/),直接提取正确的版本号:
# 替换原版本提取循环 version_pattern = re.compile(r'^(\d+\.\d+)/$') for line in stripped_content.splitlines(): line = line.strip() match = version_pattern.match(line) if match: patches_versions.append(match.group(1))
2. 文件名匹配正则的问题
原正则r'patch-.*?\.tar\.xz'用了非贪婪匹配,在部分sha256sums.asc文件中,文件名和哈希值在同一行时,可能提前终止匹配,导致无法正确捕获完整文件名。另外,findall在正则有分组时会返回分组内容而非完整匹配,这里改用finditer获取完整匹配字符串更可靠。
优化正则与匹配方式:
patch_name_pattern = re.compile(r'patch-\d+\.\d+(-rt\d+)?\.tar\.xz') # 遍历匹配时改用finditer获取完整字符串 matches = [match.group() for match in patch_name_pattern.finditer(patch_version_page_content.text)] patches_full_versions.extend(matches)
完整修复后的代码
import re import requests patches_versions = [] patches_full_versions = [] RT_PATCHES_BASE_URL = "https://cdn.kernel.org/pub/linux/kernel/projects/rt/" # 匹配版本目录行(如2.6/、6.9/) version_pattern = re.compile(r'^(\d+\.\d+)/$') # 匹配RT补丁文件名格式 patch_name_pattern = re.compile(r'patch-\d+\.\d+(-rt\d+)?\.tar\.xz') # 获取版本列表页面 patches_page_content = requests.get(RT_PATCHES_BASE_URL) patches_page_content.raise_for_status() # 清理HTML标签并提取有效版本号 stripped_content = re.sub(re.compile("<.*?>"), "", patches_page_content.text) for line in stripped_content.splitlines(): line = line.strip() match = version_pattern.match(line) if match: patches_versions.append(match.group(1)) # 遍历每个版本提取文件名 for version in patches_versions: url = f"{RT_PATCHES_BASE_URL}{version}/sha256sums.asc" patch_version_page_content = requests.get(url) patch_version_page_content.raise_for_status() # 提取所有符合格式的文件名 matches = [match.group() for match in patch_name_pattern.finditer(patch_version_page_content.text)] patches_full_versions.extend(matches) # 验证结果 print(f"处理的版本总数: {len(patches_versions)}") print(f"收集的文件总数: {len(patches_full_versions)}") print("前后各5个样本文件:", patches_full_versions[:5], patches_full_versions[-5:])
内容的提问来源于stack exchange,提问作者megalamehaxxor
相关产品推荐
相关产品推荐

