创建爬虫所需的表, 分成以下两种: 1. result table: 用户必须自定义. 保存抓取到的item结果, 一般包含title, content, url, filepath 等 2. history table: 自动创建,无需定义. 保存抓取历史, 用于去重, 包含请求的sha, json 表示, 最后更新时间, 过期时间等 ATTENTION: 每个请求只会保留一条记录
(ItemModel)
| 54 | history_item_model = {} |
| 55 | |
| 56 | def create_table(ItemModel): |
| 57 | ''' |
| 58 | 创建爬虫所需的表, 分成以下两种: |
| 59 | 1. result table: 用户必须自定义. 保存抓取到的item结果, 一般包含title, content, url, filepath 等 |
| 60 | 2. history table: 自动创建,无需定义. 保存抓取历史, 用于去重, 包含请求的sha, json 表示, 最后更新时间, 过期时间等 |
| 61 | ATTENTION: 每个请求只会保留一条记录 |
| 62 | ''' |
| 63 | if not issubclass(ItemModel, CommonFieldMixin): |
| 64 | raise ValueError('ItemModel: {} must mixin {}'.format(ItemModel.__name__, CommonFieldMixin.__name__)) |
| 65 | |
| 66 | if not issubclass(ItemModel, ItemBaseModel): |
| 67 | raise ValueError("ItemModel: {} must be subclass of {}".format(ItemModel.__name__, ItemBaseModel.__name__)) |
| 68 | |
| 69 | if not engine.dialect.has_table(engine, ItemModel.__tablename__): |
| 70 | # 表不存在, 添加create_at和update_at字段, 并建表 |
| 71 | # 创建 result table |
| 72 | ItemModel.create_at = Column(DateTime, server_default=text('CURRENT_TIMESTAMP'), doc="创建时间", comment="创建时间") |
| 73 | ItemModel.update_at = Column(DateTime, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), doc="更新时间", comment="更新时间") |
| 74 | ItemModel.__table__.create(bind=engine, checkfirst=True) |
| 75 | |
| 76 | # 创建 history table |
| 77 | table = Table(ItemModel.__tablename__ + '_history', metadata, |
| 78 | Column('id', Integer, primary_key=True, autoincrement=True), |
| 79 | Column('url_sha', CHAR(40), index=True, nullable=False, comment='请求的哈希值'), |
| 80 | Column('req_repr', String(3072), nullable=False, comment='请求的具体内容, 用json表示'), |
| 81 | Column('last_updated', TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), comment='最后一次更新时间'), |
| 82 | Column('expire', Integer, nullable=False, server_default=text('-1'), comment='有效期(秒), last_updated + expire 是过期时间, -1 表示永不过期'), |
| 83 | ) |
| 84 | table.create(bind=engine, checkfirst=True) |
| 85 | |
| 86 | # 保存 history tablename -> HistoryItemModel 的映射 |
| 87 | HistoryItemModel = type(str(table.fullname), (DynamicBaseModel,), {}) |
| 88 | HistoryItemModel.metadata = metadata |
| 89 | mapper(HistoryItemModel, table) |
| 90 | history_item_model[ItemModel] = HistoryItemModel |
| 91 | |
| 92 | |
| 93 | def query_to_sql(query): |