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

Python(sqlite3)创建子表失败,请求技术排查与解决

漫画爬虫子表未创建问题排查与修复

核心问题分析

你的代码存在几个关键错误,直接导致子表无法创建:

  • headers变量未定义:代码中调用requests.get时使用了headers参数,但从未初始化该变量,会直接抛出NameError,后续创建子表的代码根本无法执行。
  • 子表名拼接错误:遍历漫画ID时,错误使用ids[0](这是第一个漫画ID的元组,格式如(1,))而非当前循环的id[0],会生成非法表名(如ChildTable_(1,)),SQLite会拒绝创建此类表。
  • 漫画URL与子表无法对应:创建子表时重新调用get_url()爬取URL,无法保证和当前循环的漫画ID一一对应,会导致章节数据插错表,甚至重复无效爬取。
  • 缺失异常处理:爬取过程中如果请求失败、页面元素找不到,会直接抛出异常中断程序,导致子表创建流程终止。

修正后的代码

import sqlite3
from time import sleep
import requests
from bs4 import BeautifulSoup

# 初始化请求头,模拟浏览器访问
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}

connection = sqlite3.connect('parser_results.db')
cursor = connection.cursor()

# 创建父表,新增url字段用于关联章节爬取
cursor.execute('''
CREATE TABLE IF NOT EXISTS Comics (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  cover TEXT NOT NULL,
  status TEXT NOT NULL,
  url TEXT UNIQUE NOT NULL
  )
''')

def get_comic_list():
    for count in range(1, 2):
        url = f"https://asuratoon.com/manga/?page={count}&order=update"
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()  # 检查请求是否成功
            soup = BeautifulSoup(response.text, "html.parser")
            data_url = soup.find_all('div', class_='bsx')

            for comic in data_url:
                comic_url = comic.find('a').get('href')
                yield comic_url
        except Exception as e:
            print(f"列表页爬取失败: {e}")
            continue

# 爬取父表数据,同时记录漫画ID与对应URL的映射
comic_id_map = {}
for comic_url in get_comic_list():
    try:
        response = requests.get(comic_url, headers=headers)
        response.raise_for_status()
        sleep(3)
        soup = BeautifulSoup(response.text, "html.parser")

        data_general = soup.find('div', class_='bixbox animefull')
        if not data_general:
            print(f"无法获取漫画基本信息: {comic_url}")
            continue
        
        name = data_general.find('h1', class_='entry-title').text.strip()
        cover = data_general.find('img').get('src')
        status_elem = data_general.find('div', class_='imptdt')
        status = status_elem.text.replace('Status ', '').strip() if status_elem else "未知"
        
        # 插入父表并获取当前漫画ID
        cursor.execute('INSERT OR IGNORE INTO Comics (name, cover, status, url) VALUES (?, ?, ?, ?)', 
                      (name, cover, status, comic_url))
        connection.commit()
        cursor.execute('SELECT id FROM Comics WHERE url = ?', (comic_url,))
        comic_id = cursor.fetchone()[0]
        comic_id_map[comic_id] = comic_url
    except Exception as e:
        print(f"漫画详情页处理失败 {comic_url}: {e}")
        continue

# 为每个漫画创建子表并插入章节数据
for comic_id, comic_url in comic_id_map.items():
    table_name = f"Chapters_{comic_id}"
    try:
        # 创建合法命名的子表
        cursor.execute(f'''
        CREATE TABLE IF NOT EXISTS {table_name} (
                          id INTEGER PRIMARY KEY AUTOINCREMENT,
                          chapter_name TEXT NOT NULL,
                          release_date TEXT,
                          chapter_url TEXT NOT NULL UNIQUE
                      )
        ''')
        connection.commit()

        # 爬取并插入章节数据
        response = requests.get(comic_url, headers=headers)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, "html.parser")
        data = soup.find_all('div', class_='eph-num')
        
        for chapter_elem in data:
            chapter_name = chapter_elem.find('span', class_='chapternum').text.strip()
            release_date = chapter_elem.find('span', class_='chapterdate').text.strip()
            chapter_url = chapter_elem.find('a').get('href')
            
            cursor.execute(f'INSERT OR IGNORE INTO {table_name} (chapter_name, release_date, chapter_url) VALUES (?, ?, ?)', 
                          (chapter_name, release_date, chapter_url))
        connection.commit()
        print(f"子表 {table_name} 创建并填充完成")
    except Exception as e:
        print(f"章节处理失败 {comic_url}: {e}")
        continue

connection.close()

修复关键点说明

  1. 新增headers模拟浏览器请求,避免被网站拦截。
  2. 父表新增url字段,确保后续能准确关联到对应漫画的章节爬取。
  3. 使用comic_id_map字典记录漫画ID与URL的映射,避免重复爬取,保证子表与漫画一一对应。
  4. 修正子表命名逻辑,生成合法的表名(如Chapters_1)。
  5. 增加异常处理和请求状态检查,避免单个爬取失败导致整个程序中断。
  6. 使用INSERT OR IGNORE避免重复插入数据,防止重复爬取时出错。

内容的提问来源于stack exchange,提问作者Ilya Kuzin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 13:55:26