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()
修复关键点说明
- 新增
headers模拟浏览器请求,避免被网站拦截。 - 父表新增
url字段,确保后续能准确关联到对应漫画的章节爬取。 - 使用
comic_id_map字典记录漫画ID与URL的映射,避免重复爬取,保证子表与漫画一一对应。 - 修正子表命名逻辑,生成合法的表名(如
Chapters_1)。 - 增加异常处理和请求状态检查,避免单个爬取失败导致整个程序中断。
- 使用
INSERT OR IGNORE避免重复插入数据,防止重复爬取时出错。
内容的提问来源于stack exchange,提问作者Ilya Kuzin
相关产品推荐
相关产品推荐

