feapder/docs/source_code/BatchParser.md

121 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# BatchParser
BaseParser为BatchSpider的基类用来定义任务下发与数据解析是面向用户提供的接口
除了提供[BaseParser](source_code/BaseParser)所有接口外,还提供以下方法
## 方法详解
### 1. 添加任务 add_task
add_task, 每次执行start_monitor都会调用且在init_task之前调用, 用于在批次爬虫启动前添加任务到数据库
```
class TestSpider(feapder.BatchSpider):
def add_task(self):
pass
```
### 2. 更新任务
#### 方法一:
一条条更新
```python
def update_task_state(self, task_id, state=1, **kwargs):
"""
@summary: 更新任务表中任务状态,做完每个任务时代码逻辑中要主动调用
调用方法为 yield lambda : self.update_task_state(task_id, state)
---------
@param task_id: 任务id
@param state: 任务状态
---------
@result:
"""
```
举例说明
```
def parse(self, request, response):
yield item # 返回item item会自动批量入库
yield lambda : self.update_task_state(request.task_id, 1)
```
在`yield item`后,调用`self.update_task_state`函数实现任务状态更新。
这里为什么使用`yield lambda`方式呢?因为`yield item`后item不会马上入库会存在一个buffer中批量入库如果我们直接调用`self.update_task_state`更新任务状态可能这时item还并未入库如果此时程序意外退出那么缓存中的这一部分item数据将会丢失但是此时任务状态已更新任务不会重做这便会导致这个任务所对应的数据丢失
`yield lambda`返回的是一个回调函数这个函数并不会马上执行系统会保证item入库后再执行因此这么写的用意在于item入库后再更新任务状态
#### 方法二:
批量更新
```python
def update_task_batch(self, task_id, state=1, **kwargs):
"""
批量更新任务 多处调用,更新的字段必须一致
注意:需要 写成 yield update_task_batch(...) 否则不会更新
@param task_id:
@param state:
@param kwargs:
@return:
"""
```
举例说明
```python
def parse(self, request, response):
yield item # 返回item item会自动批量入库
yield self.update_task_batch(request.task_id, 1) # 更新任务状态为1
```
在`yield item`后调用`self.update_task_batch`实现批量更新
注意,批量更新必须使用 `yield`, 因为`update_task_batch`函数并未实现更新逻辑,只是返回了`UpdateItem` `UpdateItem`与`Item`类似只不过带有更新功能框架会在Item入库后在调用`UpdateItem`实现批量更新。关于`UpdateItem`详解,请参考[UpdateItem]()
#### 两种方式选取
同一张表,若更新字段相同,推荐使用批量更新的方式,效率更高,若字段不同,用一条条更新的方式。因为批量更新,这一批的更新字段必须一致
比如当请求失败时,将任务更新为-1同时标记失败原因成功时将任务更新为1写法如下
```python
def parse(self, request, response):
yield self.update_task_batch(request.task_id, 1) # 更新任务状态为1
def failed_request(self, request, response):
"""
@summary: 超过最大重试次数的request
---------
@param request:
---------
@result: request / item / callback / None (返回值必须可迭代)
"""
yield request
yield lambda : self.update_task_state(request.task_id, -1, remark="失败原因") # 更新任务状态为-1
```
因任务失败时多更新了个remark字段与任务成功时只更新state字段不同因此需要将此更新操作单独拆出来用`update_task_state`方式更新
### 3. 获取批次时间
示例:
def parse(self, request, response):
item = SpiderDataItem() # 声明一个item
item.batch_data = self.batch_date
item.title = title # 给item属性赋值
yield item # 返回item item会自动批量入库
使用`self.batch_date`可获取当前批次时间然后拼接到item入库
数据示例
| id | title | batch_date |
| --- | --- | --- |
| 1 | 百度一下 | 2021-01-01 |