You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BeautifulSoup爬虫嵌套循环变量逻辑解释及代码优化求助

原理说明

你观察到的内层循环可以正常调用外层part变量的现象,是Python的词法作用域规则导致的:Python中内层代码块默认可以读取外层作用域中已定义的、生命周期未结束的变量,不会因为多了一层循环嵌套就无法访问外层变量。

但你的代码能得到"文件名和内容正确匹配"的结果属于歪打正着,你写的内层循环本身是完全错误的冗余逻辑:
link是字符串格式的URL地址,for l in link本质是在遍历URL的每一个字符,循环变量l从头到尾都没被使用,你在内层循环里反复请求的都是同一个完整link地址,反复把相同的内容写入同一个以part命名的文件,后一次写入直接覆盖前一次的结果,所以最终文件看起来是正常的。这段冗余循环会让你对同一个页面发起十几次甚至几十次重复请求,效率极低还会给目标站点造成不必要的压力。

现存代码问题梳理
  • 存在无意义的内层遍历循环,产生大量重复无效请求
  • 缺少请求异常处理:网络波动、页面不存在、页面无article标签时会直接抛出错误中断运行
  • 未配置请求头:默认requests的UA标识很容易被站点反爬策略拦截
  • 文件名未做合规处理:链接文本如果包含/ \ : * ? " < > |这类系统禁止出现在文件名中的特殊字符,会触发文件写入错误
  • 未设置请求间隔:短时间高频请求容易被站点封禁IP
优化后代码
from bs4 import BeautifulSoup as bs
import requests
import time
import re

# 配置请求头,模拟普通浏览器访问
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
}
url = 'https://chhouk-krohom.com/'

# 捕获首页请求异常
try:
    response = requests.get(url, headers=headers, timeout=10)
    response.raise_for_status()
except Exception as e:
    print(f"首页请求失败:{str(e)}")
    exit()

soup = bs(response.content, 'html.parser')
contents = soup.select('p[style="text-align:justify;"] a')

for content in contents:
    part = content.text.strip()
    link = content['href']
    # 过滤文件名中的非法字符
    file_name = re.sub(r'[\\/*?:"<>|]', "", part)
    # 跳过空文件名、空链接的异常项
    if not file_name or not link:
        continue

    print(f"正在抓取:{part} -> {link}")
    try:
        # 发起文章页请求
        art_resp = requests.get(link, headers=headers, timeout=10)
        art_resp.raise_for_status()
        s = bs(art_resp.content, 'html.parser')
        # 判断页面是否存在article标签
        if not s.article:
            print(f"页面{link}未找到正文内容,跳过")
            continue
        main = s.article.text.strip()
        # 写入文件
        with open(f'./{file_name}.txt', mode='wt', encoding='utf-8') as file:
            file.write(main)
        print(f"{file_name}.txt 保存成功")
    except Exception as e:
        print(f"抓取{link}失败:{str(e)}")
        continue
    # 设置请求间隔,避免触发反爬
    time.sleep(1)
优化点说明
  • 删除了无意义的内层循环,每个链接仅发起一次请求
  • 增加了全链路异常捕获,单个链接抓取失败不会中断整个爬虫任务
  • 配置了浏览器UA请求头,降低被反爬拦截的概率
  • 增加了文件名非法字符过滤逻辑,避免文件写入报错
  • 增加了1秒的请求间隔,减少站点压力同时降低IP被封的风险
  • 增加了运行状态打印,方便定位抓取过程中的问题
  • 增加了空值判断,跳过异常的空链接、空标题项

内容的提问来源于stack exchange,提问作者Mortus Pect

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:12:12