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

BeautifulSoup批量爬取多页面时随机出现读取失败问题

BeautifulSoup批量爬取多页面时随机出现读取失败问题

看起来你遇到的是典型的反爬机制触发导致的随机失败,和BeautifulSoup本身没啥关系——毕竟你每次都新建了BeautifulSoup实例,换了解析器也没用,说明问题出在请求层面,不是解析环节。

核心原因应该是:你连续爬取60+页后,目标网站检测到了高频的固定请求(相同UA、无间隔),于是返回干扰内容(就是你看到的乱码body)而非正常书籍页面,自然找不到h1标签,最终返回None。

下面给你针对性的解决方案,结合你的代码来改:


1. 给请求加异常处理和状态码检查

你之前的代码直接用requests.get()却没处理请求失败的情况——比如请求超时、网站返回403/503反爬状态码,这时候page.content是异常内容,BeautifulSoup解析出来肯定找不到标题。

修改你的爬取函数:

def scrapSite(URL):
    # 先准备请求头,后面再优化UA
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0"}
    try:
        # 加超时,避免请求挂死在某个页面
        page = requests.get(URL, headers=headers, timeout=10)
        # 主动检查状态码,非200直接抛出异常(比如403反爬、500服务器错误)
        page.raise_for_status()
        soup = BeautifulSoup(page.content, "html.parser")
        title_tag = soup.find('h1', class_='book__title')
        
        # 调试用:如果没找到标题,打印页面开头内容,确认网站返回的是什么
        if not title_tag:
            print(f"⚠️ 未找到标题,页面内容预览:{page.text[:500]}...")
        
        title = title_tag.text.strip() if title_tag else 'Title not found'
        return title
    except Exception as e:
        print(f"❌ 请求/解析出错 {URL}: {str(e)}")
        return None

2. 加随机延迟+重试机制,模拟人类浏览节奏

网站大概率是通过请求间隔识别爬虫的——你连续高速爬取60+页,很容易触发频率限制。在每次请求之间加个随机延迟,遇到失败时重试几次,不要直接终止整个爬取:

import time
import random

counter = 0
books_data = []
for data in books_links:
    counter += 1
    url = data[0]
    print(f"{url} 序号: {counter}")
    
    # 加1-3秒随机延迟,避免被封
    time.sleep(random.uniform(1, 3))
    
    # 注意你之前的函数名笔误:scrapSite2应该是scrapSite吧?
    values = scrapSite(url)
    
    # 处理返回空的情况,优先重试而非直接终止
    if values is None or values == 'Title not found':
        print(f"⚠️ Values niestety none dla: {url} numer {counter}")
        # 重试机制:最多重试3次
        retry_count = 3
        while retry_count > 0 and (values is None or values == 'Title not found'):
            print(f"🔄 重试第 {4 - retry_count} 次 {url}")
            time.sleep(random.uniform(2, 4))  # 重试间隔长一点,降低被封概率
            values = scrapSite(url)
            retry_count -= 1
        
        if values is None or values == 'Title not found':
            print(f"❌ 重试失败,跳过 {url}")
            continue  # 跳过当前页面,继续爬下一个,不要直接break终止整个循环
    
    books_data.append(values)

3. 丰富请求头,避免被识别为固定爬虫

你现在用的是固定UA,网站很容易追踪到这个固定标识的高频请求。可以准备一组不同浏览器的UA,每次请求随机选一个:

# 定义一组不同设备/浏览器的UA
ua_list = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0"
]

# 修改scrapSite函数里的headers部分,每次随机选UA
def scrapSite(URL):
    headers = {"User-Agent": random.choice(ua_list)}
    try:
        page = requests.get(URL, headers=headers, timeout=10)
        page.raise_for_status()
        soup = BeautifulSoup(page.content, "html.parser")
        title_tag = soup.find('h1', class_='book__title')
        
        if not title_tag:
            print(f"⚠️ 未找到标题,页面内容预览:{page.text[:500]}...")
        
        title = title_tag.text.strip() if title_tag else 'Title not found'
        return title
    except Exception as e:
        print(f"❌ 请求/解析出错 {URL}: {str(e)}")
        return None

如果嫌维护UA列表麻烦,也可以用fake_useragent库(先执行pip install fake_useragent安装),它会自动获取最新的UA:

from fake_useragent import UserAgent
ua = UserAgent()
headers = {"User-Agent": ua.random}

为什么换解析器没用?

因为问题根本不在解析器——当网站返回的是干扰内容(乱码、403反爬页面、验证码页面),不管用什么解析器,都找不到你要的h1标签,所以换解析器解决不了问题,核心是要绕过网站的反爬限制。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:37:59