1. XXX招标网概述
xxx招标网是官方政府采购信息发布平台,提供政府采购公告、中标公告、更正公告等各类政府采购信息。该网站是获取政府采购信息的权威来源,对于需要了解政府采购动态、参与政府采购活动的企业和机构具有重要参考价值。通过三天开发已经实现了容错、调度、写库等,正常运行4天了!
2. 爬虫系统架构
2.1 核心功能
-
验证码处理:自动识别和处理网站验证码,支持PaddleOCR识别
-
重试机制:针对页面超时等问题实现自动重试
-
模拟事件:模拟用户操作,如点击、输入等
-
动态HTML解析:处理JavaScript动态生成的内容
-
定时任务:基于APScheduler的定时任务调度
-
数据存储:支持文件系统和数据库存储
-
增量爬取:只爬取新增的项目信息
2.2 技术栈
-
Python 3.8+:主要开发语言
-
Selenium:模拟浏览器操作
-
BeautifulSoup:HTML解析
-
PaddleOCR:验证码识别
-
APScheduler:定时任务调度
-
PostgreSQL:数据库存储
-
JSON:数据序列化
3. 爬虫功能详解
3.1 验证码处理
-
自动识别:使用PaddleOCR识别验证码图片
-
图像预处理:对验证码图片进行去噪、增强处理
-
多尝试机制:识别失败时自动重试,最多尝试3次
-
错误检测:检测验证码错误提示,及时重新识别
3.2 重试机制
-
页面超时重试:当页面加载超时时,自动重新加载页面
-
递增等待时间:随着重试次数增加,延长等待时间
-
错误分类:区分超时错误、内容未找到错误等不同类型
-
数据库记录:将重试状态记录到数据库,支持后台监控
3.3 模拟事件
-
页面跳转:模拟用户点击分页、详情页等操作
-
表单填写:自动填写搜索参数
-
下拉菜单选择:模拟选择公告类型等操作
-
JavaScript执行:执行页面JavaScript获取动态数据
3.4 动态HTML解析
-
Vue数据提取:从Vue组件中提取数据
-
多源数据获取:从#noticeArea、Vue数据、页面脚本等多个来源获取数据
-
表格数据解析:解析不同格式的HTML表格
-
发布时间提取:从多个可能的字段中提取发布时间
3.5 定时任务
-
基于数据库配置:从数据库读取定时任务配置
-
多任务调度:支持多个定时任务并行执行
-
任务状态监控:记录任务执行状态和结果
-
灵活的cron表达式:支持复杂的定时调度需求
4. 代码结构
4.1 目录结构
go
crawlerpurchase/
├── main_crawler.py # 主爬虫程序
├── scheduler_service.py # 定时任务调度服务
├── db_service.py # 数据库服务
├── data_writer.py # 数据写入服务
├── db_models.py # 数据库模型
├── bid_parser.py # 中标公告解析器
├── procurement_parser.py # 采购公告解析器
├── data_storage.py # 数据存储服务
├── search_config.py # 搜索配置
├── database_migration.sql # 数据库迁移脚本
├── run_migration.py # 运行数据库迁移
├── scheduler_runner.py # 调度器运行器
└── data/ # 数据存储目录
├── ggxx/ # 采购公告数据
│ ├── html_pages/ # 详情页HTML
│ └── details/ # 解析后的详情
└── zbgg/ # 中标公告数据
├── html_pages/ # 详情页HTML
└── details/ # 解析后的详情
4.2 核心文件功能
| 文件名 | 主要功能 |
|---|---|
| main_crawler.py | 主爬虫程序,负责页面爬取、验证码处理、数据解析 |
| scheduler_service.py | 定时任务调度服务,基于APScheduler实现 |
| db_service.py | 数据库操作服务,提供数据库读写功能 |
| data_writer.py | 数据写入服务,将爬取的数据写入数据库 |
| bid_parser.py | 中标公告解析器,解析中标公告详情 |
| procurement_parser.py | 采购公告解析器,解析采购公告详情 |
5. 数据库设计
5.1 核心表结构
5.1.1 爬虫任务配置表(crawl_tasks)
| 字段名 | 数据类型 | 约束 | 描述 |
|---|---|---|---|
| id | SERIAL | PRIMARY KEY | 任务ID |
| task_name | VARCHAR(255) | NOT NULL | 任务名称 |
| cron_expression | VARCHAR(100) | NOT NULL | Cron表达式 |
| notice_types | VARCHAR(100) | NOT NULL | 公告类型(ggxx,zbgg) |
| status | VARCHAR(50) | NOT NULL | 任务状态(active,inactive) |
| description | TEXT | 任务描述 | |
| max_retry_count | INTEGER | NOT NULL DEFAULT 3 | 最大重试次数 |
| timeout_minutes | INTEGER | NOT NULL DEFAULT 30 | 超时时间(分钟) |
| create_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 创建时间 |
5.1.2 每日任务记录表(daily_task_records)
| 字段名 | 数据类型 | 约束 | 描述 |
|---|---|---|---|
| id | SERIAL | PRIMARY KEY | 记录ID |
| task_id | INTEGER | REFERENCES crawl_tasks(id) | 任务ID |
| start_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 开始时间 |
| end_time | TIMESTAMP | 结束时间 | |
| status | VARCHAR(50) | NOT NULL | 任务状态(running,completed,failed) |
| total_projects | INTEGER | DEFAULT 0 | 总项目数 |
| success_count | INTEGER | DEFAULT 0 | 成功数 |
| failed_count | INTEGER | DEFAULT 0 | 失败数 |
| error_message | TEXT | 错误信息 | |
| update_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 更新时间 |
5.1.3 爬取记录状态表(crawl_records)
| 字段名 | 数据类型 | 约束 | 描述 |
|---|---|---|---|
| id | SERIAL | PRIMARY KEY | 记录ID |
| project_id | VARCHAR(255) | NOT NULL | 项目ID |
| notice_type | VARCHAR(50) | NOT NULL | 公告类型 |
| detail_url | TEXT | NOT NULL | 详情URL |
| task_record_id | INTEGER | REFERENCES daily_task_records(id) | 任务记录ID |
| status | VARCHAR(50) | NOT NULL | 爬取状态(pending,success,failed) |
| retry_count | INTEGER | NOT NULL DEFAULT 0 | 重试次数 |
| max_retry_count | INTEGER | NOT NULL DEFAULT 3 | 最大重试次数 |
| error_message | TEXT | 错误信息 | |
| error_type | VARCHAR(50) | 错误类型 | |
| create_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 创建时间 |
| update_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 更新时间 |
5.1.4 项目信息表(projects)
| 字段名 | 数据类型 | 约束 | 描述 |
|---|---|---|---|
| id | SERIAL | PRIMARY KEY | 项目ID |
| project_id | VARCHAR(255) | NOT NULL UNIQUE | 网站项目ID |
| title | TEXT | NOT NULL | 项目标题 |
| detail_url | TEXT | NOT NULL | 详情URL |
| notice_type | VARCHAR(50) | NOT NULL | 公告类型 |
| publish_date | TIMESTAMP | 发布时间 | |
| purchaser | VARCHAR(255) | 采购人 | |
| agency | VARCHAR(255) | 代理机构 | |
| district | VARCHAR(255) | 区划 | |
| create_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 创建时间 |
| update_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 更新时间 |
5.1.5 中标结果表(bid_results)
| 字段名 | 数据类型 | 约束 | 描述 |
|---|---|---|---|
| id | SERIAL | PRIMARY KEY | 结果ID |
| project_id | VARCHAR(255) | NOT NULL | 项目ID |
| package_name | VARCHAR(255) | NOT NULL | 采购包名称 |
| supplier_name | VARCHAR(255) | NOT NULL | 供应商名称 |
| supplier_address | TEXT | 供应商地址 | |
| bid_amount | VARCHAR(255) | 中标金额 | |
| execution_standard | TEXT | 执行标准 | |
| total_score | NUMERIC(5,2) | 评审总得分 | |
| review_price | VARCHAR(255) | 评审价格 | |
| create_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 创建时间 |
| update_time | TIMESTAMP | NOT NULL DEFAULT NOW() | 更新时间 |
6. 定时任务配置
6.1 推荐的定时任务配置
| 任务名称 | Cron表达式 | 公告类型 | 描述 |
|---|---|---|---|
| 采购公告每日爬取-上午 | 0 9 * * * | ggxx | 每天上午9点爬取采购公告 |
| 采购公告每日爬取-下午 | 0 15 * * * | ggxx | 每天下午3点爬取采购公告 |
| 中标公告每日爬取-上午 | 30 9 * * * | zbgg | 每天上午9:30爬取中标公告 |
| 中标公告每日爬取-下午 | 30 15 * * * | zbgg | 每天下午3:30爬取中标公告 |
| 全量公告每周爬取 | 0 2 * * 0 | ggxx,zbgg | 每周日凌晨2点全量爬取所有公告 |
7. 运行方式
7.1 实时爬取
go
# 直接运行主爬虫
python main_crawler.py
# 指定爬取类型
python main_crawler.py --notice_types ggxx,zbgg
7.2 定时任务
go
# 启动定时任务调度器
python scheduler_service.py
8. 注意事项
-
反爬措施:网站可能会采取反爬措施,如验证码、IP限制等,爬虫已实现相应的处理机制
-
数据更新:网站结构可能会变化,需要定期检查和更新爬虫代码
-
性能优化:对于大量数据的爬取,建议合理设置爬取间隔,避免对网站造成过大压力
-
错误处理:爬虫已实现错误处理和重试机制,但仍可能遇到未处理的异常情况
-
数据库维护:定期清理过期数据,优化数据库性能
9. 故障排查
9.1 常见错误及解决方案
| 错误信息 | 可能原因 | 解决方案 |
|---|---|---|
| 验证码识别失败 | 验证码过于复杂或OCR模型不匹配 | 尝试更新OCR模型或调整图像预处理参数 |
| 页面加载超时 | 网络问题或网站响应慢 | 增加超时时间,实现重试机制 |
| 数据解析失败 | 页面结构变化 | 检查并更新解析规则 |
| 数据库连接失败 | 数据库配置错误或网络问题 | 检查数据库配置和网络连接 |
| 定时任务未执行 | 调度器配置错误 | 检查cron表达式和任务配置 |
10. 总结
XXX招标网爬虫系统是一个功能完善、技术先进的信息采集系统,通过自动化的方式获取政府采购信息,为用户提供及时、准确的政府采购数据。系统采用了多种先进技术,如验证码识别、动态HTML解析、定时任务调度等,确保了爬虫的稳定性和可靠性。同时,系统设计了完善的数据库结构,支持数据的存储、管理和分析,为后续的数据分析和应用提供了基础。
通过该爬虫系统,用户可以:
-
实时获取最新的政府采购信息
-
了解政府采购市场动态
-
分析政府采购趋势
-
为参与政府采购活动提供参考
系统具有良好的可扩展性和维护性,可以根据实际需求进行调整和优化,以适应不断变化的网站结构和业务需求。