# base-async-spider **Repository Path**: chenyuxini/base-async-spider ## Basic Information - **Project Name**: base-async-spider - **Description**: 本项目是一个基于Python异步IO的可扩展、轻量级网络爬虫框架。它包含一个基础引擎、URL池、异步内容下载器和数据存储模块(如SQLite),旨在高效、稳定地抓取和处理网页数据。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-09-16 - **Last Updated**: 2025-09-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: Python, Spider, 异步爬虫, 线程 ## README # Base Async Spider - 基础异步爬虫引擎 一个基于 Python asyncio 的高性能异步爬虫框架,支持多种数据存储方式和灵活的解析器配置。 ## 🚀 特性 - **异步高性能**: 基于 asyncio 实现,支持高并发爬取 - **模块化设计**: 引擎、解析器、存储器、URL 池等组件独立可配置 - **多存储支持**: 支持 SQLite、MySQL、MongoDB、JSON、CSV、TXT 等多种存储方式 - **智能 URL 管理**: 自动去重,支持动态添加新 URL - **灵活解析器**: 支持自定义数据解析逻辑 - **完善日志系统**: 详细的日志记录和错误处理 - **配置驱动**: 通过 YAML 配置文件管理所有参数 ## 📁 项目结构 ``` base-async-spider/ ├── config.yaml # 配置文件 ├── demo.py # 使用示例 ├── logger.py # 日志模块 ├── requirements.txt # 依赖包 ├── engine/ # 爬虫引擎 │ ├── __init__.py │ └── base_engine.py # 基础引擎类 ├── contentDownloader/ # 内容下载器 │ ├── __init__.py │ └── content_download.py # 异步下载器 ├── parseData/ # 数据解析器 │ ├── __init__.py │ └── custom.py # 自定义解析器示例 ├── saveData/ # 数据存储器 │ ├── __init__.py │ └── sqliteSave.py # SQLite存储器 ├── urlPool/ # URL池管理 │ ├── __init__.py │ └── url_pool.py # URL池类 ├── crawled_data/ # 爬取数据存储目录 └── logs/ # 日志文件目录 ``` ## 🛠️ 安装 1. 克隆项目 ```bash git clone https://gitee.com/chenyuxini/base-async-spider.git cd base-async-spider ``` 2. 安装依赖 ```bash pip install -r requirements.txt ``` 或使用国内镜像 ```bash pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ ``` ## ⚙️ 配置 编辑 `config.yaml` 文件来配置爬虫参数: ```yaml # 存储配置 storage: sources: sqlite: enabled: true # 启用SQLite存储 path: ./crawled_data/sqlite filename: spider_data.db database: spider_db # 日志配置 logging: level: INFO dir: ./logs # 爬虫配置 crawler: workers: 5 # Worker协程数量 concurrency: 10 # 并发限制 timeout: 10 # 请求超时时间(秒) interval: 1 # 请求间隔时间(秒),防止请求过于频繁 # HTTP配置 http: user_agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' connector: limit: 100 # 总连接数限制 limit_per_host: 30 # 每个主机的连接数限制 ``` ## 🚀 快速开始 ### 基本使用示例 ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- import asyncio from parseData import parser_custom_data from saveData.sqliteSave import SqliteSaver from engine.base_engine import BaseEngine async def movieBase(): """获取电影基础信息""" # 定义起始URL列表 start_urls = [ 'https://www.1905.com/mdb/film/list/country-China/o0d0p1.html' ] # 创建SQLite保存器实例 sqlite_saver = SqliteSaver() # 检查SQLite是否启用 if not sqlite_saver.is_enabled(): print("SQLite未启用,请检查配置文件") return # 创建保存函数(绑定表名和索引字段) async def movie_save_func(data, url): await sqlite_saver.save(data, url, 'movies', 'title') # 创建并启动爬虫引擎 engine = BaseEngine( start_urls=start_urls, parse_func=parser_custom_data, save_func=movie_save_func ) # 启动爬虫 await engine.start() if __name__ == '__main__': asyncio.run(movieBase()) ``` ### 运行示例 ```bash python demo.py ``` ## 📖 核心组件 ### 1. BaseEngine - 基础引擎 核心爬虫引擎,负责协调各个组件: ```python engine = BaseEngine( start_urls=['https://example.com'], # 起始URL列表 parse_func=your_parse_function, # 解析函数 save_func=your_save_function # 保存函数 ) await engine.start() ``` ### 2. 解析器 (ParseData) 自定义数据解析器,需要返回 `(parsed_data, new_urls)` 元组: ```python def parser_custom_data(content: str, source_url: str) -> tuple[list[dict], list[str]] | None: """ 自定义解析器 Args: content: 网页内容 source_url: 来源URL Returns: (parsed_data, new_urls): 解析的数据列表和新发现的URL列表 """ # 解析逻辑 parsed_data = [] # 解析后的数据列表 new_urls = [] # 新发现的URL列表 return parsed_data, new_urls ``` ### 3. 存储器 (SaveData) 支持多种存储方式,以 SQLite 为例: ```python from saveData.sqliteSave import SqliteSaver sqlite_saver = SqliteSaver() # 保存数据 await sqlite_saver.save( data=parsed_data, # 数据列表 source_url=url, # 来源URL table_name='movies', # 表名 index_field='title' # 索引字段(可选) ) ``` ### 4. URL 池 (URLPool) 自动管理 URL 队列,支持去重: ```python from urlPool import URLPool url_pool = URLPool() await url_pool.add_url('https://example.com') # 添加URL url = await url_pool.get_url() # 获取URL ``` ### 5. 内容下载器 (ContentDownloader) 异步 HTTP 下载器: ```python from contentDownloader import ContentDownloader async with ContentDownloader(timeout=10) as downloader: content = await downloader.download('https://example.com') ``` ## 🔧 高级配置 ### 请求间隔控制 为了防止请求过于频繁被网站封禁,爬虫支持请求间隔功能: ```yaml crawler: interval: 1 # 请求间隔时间(秒) ``` **效果说明:** - `interval: 0` - 无间隔,连续请求(默认) - `interval: 1` - 每次请求间隔 1 秒 - `interval: 2` - 每次请求间隔 2 秒 - `interval: 0.5` - 每次请求间隔 0.5 秒 **工作原理:** 1. 每次调用 `download()` 方法前,会检查距离上次请求的时间 2. 如果间隔时间不足,会自动等待到指定间隔时间 3. 确保多个 Worker 协程之间也遵循间隔规则 4. 在 DEBUG 日志级别下会显示等待信息 **使用建议:** - 对于友好网站:`interval: 0.5-1` - 对于敏感网站:`interval: 2-5` - 对于 API 接口:`interval: 0.1-0.5` ### 多存储支持 在 `config.yaml` 中配置多种存储方式: ```yaml storage: sources: sqlite: enabled: true path: ./data/sqlite filename: data.db mysql: enabled: false host: localhost port: 3306 user: root password: password database: spider_data mongodb: enabled: false host: localhost port: 27017 database: spider_data collection: crawled_data ``` ### 自定义解析器 创建自定义解析器: ```python def my_parser(content: str, url: str) -> tuple[list[dict], list[str]] | None: """自定义解析器示例""" from lxml import etree try: html = etree.HTML(content) # 解析数据 data_list = [] for item in html.xpath('//div[@class="item"]'): data = { 'title': item.xpath('.//h3/text()')[0] if item.xpath('.//h3/text()') else '', 'url': item.xpath('.//a/@href')[0] if item.xpath('.//a/@href') else '' } data_list.append(data) # 提取新URL new_urls = html.xpath('//a/@href') new_urls = [url for url in new_urls if url.startswith('http')] return data_list, new_urls except Exception as e: print(f"解析错误: {e}") return None ``` ## 📊 数据存储 ### SQLite 存储 数据会自动保存到 SQLite 数据库,表结构根据解析的数据动态创建: ```sql -- 示例表结构 CREATE TABLE movies ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, score TEXT, time TEXT, actor TEXT, type TEXT, detail_url TEXT, img TEXT, source_url TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` ### 查看数据 ```python import sqlite3 # 连接数据库 conn = sqlite3.connect('./crawled_data/sqlite/spider_data.db') cursor = conn.cursor() # 查询数据 cursor.execute("SELECT * FROM movies LIMIT 10") results = cursor.fetchall() for row in results: print(row) conn.close() ``` ## 📝 日志系统 项目包含完善的日志系统,支持不同级别的日志记录: - **DEBUG**: 详细的调试信息 - **INFO**: 一般信息记录 - **WARNING**: 警告信息 - **ERROR**: 错误信息 - **CRITICAL**: 严重错误 日志文件保存在 `logs/` 目录下,按日期命名。 ## 🐛 故障排除 ### 常见问题 1. **SQLite 未启用** - 检查 `config.yaml` 中 `storage.sources.sqlite.enabled` 是否为 `true` 2. **依赖包缺失** - 运行 `pip install -r requirements.txt` 安装所有依赖 3. **网络连接问题** - 检查网络连接和代理设置 - 调整 `timeout` 配置 4. **解析器错误** - 检查解析器函数返回值格式 - 确保返回 `(parsed_data, new_urls)` 元组 ### 调试模式 启用 DEBUG 日志级别进行调试: ```yaml logging: level: DEBUG ``` ## 📄 许可证 本项目采用 [MIT 许可证](LICENSE) - 查看 LICENSE 文件了解详情。 ## ⚠️ 免责声明 **注意**: 请遵守网站的 robots.txt 规则和相关法律法规,合理使用爬虫工具。本项目仅供学习和研究使用,使用者需自行承担使用风险。