fast-crawl-core 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. fast_crawl_core-0.0.1/MANIFEST.in +0 -0
  2. fast_crawl_core-0.0.1/PKG-INFO +16 -0
  3. fast_crawl_core-0.0.1/README.rst +4 -0
  4. fast_crawl_core-0.0.1/fast_crawl_core/__init__.py +1 -0
  5. fast_crawl_core-0.0.1/fast_crawl_core/client/__init__.py +0 -0
  6. fast_crawl_core-0.0.1/fast_crawl_core/client/mongo_client.py +104 -0
  7. fast_crawl_core-0.0.1/fast_crawl_core/client/portainer_client.py +85 -0
  8. fast_crawl_core-0.0.1/fast_crawl_core/client/redis_client.py +22 -0
  9. fast_crawl_core-0.0.1/fast_crawl_core/dao/__init__.py +0 -0
  10. fast_crawl_core-0.0.1/fast_crawl_core/dao/auth_user_spider_group.py +69 -0
  11. fast_crawl_core-0.0.1/fast_crawl_core/dao/batch_spider.py +47 -0
  12. fast_crawl_core-0.0.1/fast_crawl_core/dao/batch_spider_group.py +67 -0
  13. fast_crawl_core-0.0.1/fast_crawl_core/dao/meta.py +32 -0
  14. fast_crawl_core-0.0.1/fast_crawl_core/dao/node.py +27 -0
  15. fast_crawl_core-0.0.1/fast_crawl_core/dao/spider.py +58 -0
  16. fast_crawl_core-0.0.1/fast_crawl_core/dao/spider_group.py +67 -0
  17. fast_crawl_core-0.0.1/fast_crawl_core/dao/stream_spider.py +41 -0
  18. fast_crawl_core-0.0.1/fast_crawl_core/dao/stream_spider_group.py +40 -0
  19. fast_crawl_core-0.0.1/fast_crawl_core/model/__init__.py +0 -0
  20. fast_crawl_core-0.0.1/fast_crawl_core/model/base.py +59 -0
  21. fast_crawl_core-0.0.1/fast_crawl_core/model/batch.py +110 -0
  22. fast_crawl_core-0.0.1/fast_crawl_core/model/entity.py +212 -0
  23. fast_crawl_core-0.0.1/fast_crawl_core/model/enums.py +93 -0
  24. fast_crawl_core-0.0.1/fast_crawl_core/model/rabbit.py +38 -0
  25. fast_crawl_core-0.0.1/fast_crawl_core/model/stream.py +68 -0
  26. fast_crawl_core-0.0.1/fast_crawl_core/publish/__init__.py +0 -0
  27. fast_crawl_core-0.0.1/fast_crawl_core/publish/batch.py +252 -0
  28. fast_crawl_core-0.0.1/fast_crawl_core/publish/stream.py +234 -0
  29. fast_crawl_core-0.0.1/fast_crawl_core/receive/__init__.py +0 -0
  30. fast_crawl_core-0.0.1/fast_crawl_core/receive/async_receuver.py +86 -0
  31. fast_crawl_core-0.0.1/fast_crawl_core/receive/exceptions.py +11 -0
  32. fast_crawl_core-0.0.1/fast_crawl_core/receive/key_builder.py +27 -0
  33. fast_crawl_core-0.0.1/fast_crawl_core/receive/model.py +66 -0
  34. fast_crawl_core-0.0.1/fast_crawl_core/receive/processor.py +46 -0
  35. fast_crawl_core-0.0.1/fast_crawl_core/receive/receiver.py +192 -0
  36. fast_crawl_core-0.0.1/fast_crawl_core/service/__init__.py +0 -0
  37. fast_crawl_core-0.0.1/fast_crawl_core/service/base.py +23 -0
  38. fast_crawl_core-0.0.1/fast_crawl_core/service/batch_spider.py +10 -0
  39. fast_crawl_core-0.0.1/fast_crawl_core/service/batch_spider_group.py +26 -0
  40. fast_crawl_core-0.0.1/fast_crawl_core/service/spider.py +16 -0
  41. fast_crawl_core-0.0.1/fast_crawl_core/service/spider_group.py +35 -0
  42. fast_crawl_core-0.0.1/fast_crawl_core/service/stream_spider.py +20 -0
  43. fast_crawl_core-0.0.1/fast_crawl_core/service/stream_spider_group.py +50 -0
  44. fast_crawl_core-0.0.1/fast_crawl_core/util/__init__.py +0 -0
  45. fast_crawl_core-0.0.1/fast_crawl_core/util/cfg.py +60 -0
  46. fast_crawl_core-0.0.1/fast_crawl_core/util/decator.py +13 -0
  47. fast_crawl_core-0.0.1/fast_crawl_core/util/exceptions.py +11 -0
  48. fast_crawl_core-0.0.1/fast_crawl_core/util/logger.py +51 -0
  49. fast_crawl_core-0.0.1/fast_crawl_core/util/rabbit_key.py +21 -0
  50. fast_crawl_core-0.0.1/fast_crawl_core/util/redis_key.py +21 -0
  51. fast_crawl_core-0.0.1/fast_crawl_core/util/sequence.py +34 -0
  52. fast_crawl_core-0.0.1/fast_crawl_core/util/time.py +151 -0
  53. fast_crawl_core-0.0.1/fast_crawl_core.egg-info/PKG-INFO +16 -0
  54. fast_crawl_core-0.0.1/fast_crawl_core.egg-info/SOURCES.txt +57 -0
  55. fast_crawl_core-0.0.1/fast_crawl_core.egg-info/dependency_links.txt +1 -0
  56. fast_crawl_core-0.0.1/fast_crawl_core.egg-info/requires.txt +1 -0
  57. fast_crawl_core-0.0.1/fast_crawl_core.egg-info/top_level.txt +1 -0
  58. fast_crawl_core-0.0.1/setup.cfg +4 -0
  59. fast_crawl_core-0.0.1/setup.py +20 -0
File without changes
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.1
2
+ Name: fast-crawl-core
3
+ Version: 0.0.1
4
+ Summary: fast crawl core for zsodata
5
+ Home-page: http://www.zsodata.com
6
+ Author: zsodata
7
+ Author-email: team@zso.io
8
+ License: BSD License
9
+ Platform: all
10
+ Requires-Python: >=3.7
11
+ Requires-Dist: zcbot-url-parser
12
+
13
+ pip uninstall fast-crawl-core
14
+
15
+ pip install --upgrade fast-crawl-core -i https://pypi.python.org/simple
16
+ pip show fast-crawl-core
@@ -0,0 +1,4 @@
1
+ pip uninstall fast-crawl-core
2
+
3
+ pip install --upgrade fast-crawl-core -i https://pypi.python.org/simple
4
+ pip show fast-crawl-core
@@ -0,0 +1 @@
1
+ from __future__ import absolute_import
@@ -0,0 +1,104 @@
1
+ # -*- coding: utf-8 -*-
2
+ import pytz
3
+ from motor.motor_asyncio import AsyncIOMotorClient
4
+
5
+ from ..util import cfg
6
+ from ..util.exceptions import NoConfigException
7
+ from ..util.decator import singleton
8
+
9
+
10
+ @singleton
11
+ class Mongo(object):
12
+ """
13
+ Mongo异步客户端简易封装(使用motor)
14
+ """
15
+
16
+ def __init__(self, mongo_uri: str = None, mongo_db: str = None, *args, **kwargs):
17
+ self.mongo_uri = mongo_uri or cfg.get('ZCBOT_CORE_MONGO_URL')
18
+ self.mongo_db = mongo_db or cfg.get('ZCBOT_CORE_MONGO_DB')
19
+ if not self.mongo_uri:
20
+ raise NoConfigException('mongodb uri not config!')
21
+ if not self.mongo_db:
22
+ raise NoConfigException('mongodb database not config!')
23
+
24
+ self.client = AsyncIOMotorClient(self.mongo_uri, tz_aware=True, tzinfo=pytz.timezone('Asia/Shanghai'))
25
+ self.db = self.client[self.mongo_db]
26
+
27
+ # 获取集合
28
+ def get_collection(self, coll):
29
+ return self.db.get_collection(coll)
30
+
31
+ # 查询对象
32
+ async def get(self, collection, query={}):
33
+ result = await self.db[collection].find_one(query)
34
+ return result
35
+
36
+ # 统计数量
37
+ async def count(self, collection, query={}):
38
+ return await self.db[collection].count_documents(query)
39
+
40
+ # 查询列表
41
+ async def list(self, collection, query={}, fields=None, sort=[]):
42
+ if fields:
43
+ cursor = self.db[collection].find(query, fields, sort=sort)
44
+ else:
45
+ cursor = self.db[collection].find(query, sort=sort)
46
+ return await cursor.to_list(length=None)
47
+
48
+ # 查询去重列表
49
+ async def distinct(self, collection, dist_key, query={}, fields=None):
50
+ return await self.db[collection].find(query, fields).distinct(dist_key)
51
+
52
+ # 聚合查询
53
+ async def aggregate(self, collection, pipeline=[]):
54
+ cursor = self.db[collection].aggregate(pipeline, allowDiskUse=True)
55
+ return await cursor.to_list(length=None)
56
+
57
+ # 查询分页列表
58
+ async def list_with_page(self, collection, query={}, page_size=10000, fields=None):
59
+ rows = list()
60
+ total = await self.db[collection].count_documents(query)
61
+ if total > 0 and page_size > 0:
62
+ total_page = round(total / page_size)
63
+ for page in range(0, total_page):
64
+ if fields:
65
+ cursor = self.db[collection].find(query, fields).skip(page_size * page).limit(page)
66
+ else:
67
+ cursor = self.db[collection].find(query).skip(page_size * page).limit(page)
68
+ curr_batch = await cursor.to_list(length=None)
69
+ if curr_batch:
70
+ rows.append(curr_batch)
71
+ return rows
72
+
73
+ # 插入或更新
74
+ async def insert_or_update(self, collection, data, id_key='_id'):
75
+ return await self.db[collection].update_one({id_key: data[id_key]}, {'$set': data}, upsert=True)
76
+
77
+ # 更新
78
+ async def update(self, collection, filter, data, multi=False):
79
+ if multi:
80
+ return await self.db[collection].update_many(filter, {'$set': data})
81
+ return await self.db[collection].update_one(filter, {'$set': data})
82
+
83
+ # 以主键更新
84
+ async def update_by_pk(self, collection, pk_val, data):
85
+ return await self.db[collection].update_one({'_id': pk_val}, {'$set': data})
86
+
87
+ # 批量更新
88
+ async def batch_update(self, collection, filter, datas, multi=False):
89
+ if multi:
90
+ return await self.db[collection].update_many(filter, datas)
91
+ return await self.db[collection].update_one(filter, datas)
92
+
93
+ # 删除
94
+ async def delete(self, collection, filter):
95
+ return await self.db[collection].delete_many(filter)
96
+
97
+ # 批量写入
98
+ async def bulk_write(self, collection, bulk_list):
99
+ if bulk_list:
100
+ return await self.db[collection].bulk_write(bulk_list, ordered=False, bypass_document_validation=True)
101
+
102
+ # 关闭链接
103
+ def close(self):
104
+ self.client.close()
@@ -0,0 +1,85 @@
1
+ # -*- coding: utf-8 -*-
2
+ import json
3
+ import aiohttp
4
+ from ..util import logger
5
+ from ..util.decator import singleton
6
+ from ..model.entity import PortainerNode, BatchSpider
7
+
8
+ LOGGER = logger.get('容器')
9
+
10
+
11
+ @singleton
12
+ class PortainerClient(object):
13
+ """
14
+ Portainer异步客户端简易封装(使用aiohttp)
15
+ """
16
+
17
+ def __init__(self):
18
+ self.user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4208.400'
19
+ # 客户端
20
+ self.create_api = '{}/api/endpoints/{}/docker/containers/create?name={}'
21
+ self.start_api = '{}/api/endpoints/{}/docker/containers/{}/start'
22
+ self.stop_api = '{}/api/endpoints/{}/docker/containers/{}/kill'
23
+
24
+ async def create_container(self, node: PortainerNode, spider: BatchSpider, container_name: str, param_data):
25
+ container_conf = {
26
+ "Cmd": [
27
+ "/bin/sh",
28
+ "-c",
29
+ spider.param % param_data
30
+ ],
31
+ "Env": spider.env,
32
+ "Image": spider.dockerImage
33
+ }
34
+
35
+ async with aiohttp.ClientSession() as session:
36
+ async with session.post(
37
+ url=self.create_api.format(node.apiBaseUrl, node.endpointId, container_name),
38
+ headers={
39
+ 'X-API-Key': node.apiToken,
40
+ 'User-Agent': self.user_agent,
41
+ 'Content-Type': 'application/json;charset=UTF-8',
42
+ },
43
+ data=json.dumps(container_conf)
44
+ ) as resp:
45
+ text = await resp.text()
46
+ if resp.status in [200, 201]:
47
+ data = json.loads(text) or {}
48
+ if data.get('Id', None):
49
+ id = data.get('Id', '')
50
+ LOGGER.info(f'创建成功: id={id}, endpoint={node.endpointId} name={container_name}')
51
+ return id
52
+
53
+ LOGGER.error(f'创建失败: result={text}, endpoint={node.endpointId} name={container_name}')
54
+
55
+ async def start(self, node: PortainerNode, container_id: str):
56
+ async with aiohttp.ClientSession() as session:
57
+ async with session.post(
58
+ url=self.start_api.format(node.apiBaseUrl, node.endpointId, container_id),
59
+ headers={
60
+ 'X-API-Key': node.apiToken,
61
+ 'User-Agent': self.user_agent,
62
+ 'Content-Type': 'application/json;charset=UTF-8',
63
+ }
64
+ ) as resp:
65
+ if resp.status in [204, 200]:
66
+ LOGGER.info(f'启动成功: id={container_id}')
67
+ return container_id
68
+
69
+ LOGGER.error(f'启动失败: id={container_id}')
70
+
71
+ async def stop(self, node: PortainerNode, container_id: str):
72
+ async with aiohttp.ClientSession() as session:
73
+ async with session.post(
74
+ url=self.stop_api.format(node.apiBaseUrl, node.endpointId, container_id),
75
+ headers={
76
+ 'X-API-Key': node.apiToken,
77
+ 'User-Agent': self.user_agent,
78
+ 'Content-Type': 'application/json;charset=UTF-8',
79
+ }
80
+ ) as resp:
81
+ if resp.status in [204, 200]:
82
+ LOGGER.info(f'停止成功: id={container_id}')
83
+ return container_id
84
+
85
+ LOGGER.error(f'停止失败: id={container_id}')
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ import redis.asyncio as aioredis
3
+ from ..util import cfg
4
+ from ..util.decator import singleton
5
+ from ..util.exceptions import NoConfigException
6
+
7
+
8
+ @singleton
9
+ class Redis(object):
10
+ """
11
+ Redis异步客户端简易封装(单例,使用redis.asyncio)
12
+ """
13
+
14
+ def __init__(self, redis_uri: str = None, redis_db: int = None, decode_responses=True):
15
+ self.redis_uri = redis_uri or cfg.get('ZCBOT_CORE_REDIS_URL')
16
+ self.redis_db = redis_db or cfg.get('ZCBOT_CORE_REDIS_DB')
17
+ if not self.redis_uri:
18
+ raise NoConfigException('redis uri not config!')
19
+ if not self.redis_db:
20
+ raise NoConfigException('redis database not config!')
21
+
22
+ self.client = aioredis.Redis.from_url(url=self.redis_uri, db=self.redis_db, decode_responses=decode_responses)
File without changes
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import List
3
+ from ..client.mongo_client import Mongo
4
+
5
+
6
+ # 获取支持网站平台
7
+ async def get_platforms_by_group(group_code: str, enable: int = None):
8
+ _query = {}
9
+ if group_code:
10
+ _query["groupCode"] = group_code
11
+ if enable is not None:
12
+ _query["enable"] = enable
13
+
14
+ return await Mongo().list('zcbot_auth_user_spider_group', query=_query)
15
+
16
+
17
+ async def get_platforms_by_group_code(group_code: str, enable):
18
+ _query = {
19
+ "groupCode": group_code
20
+ }
21
+ _fields = {
22
+ "spiders": 0,
23
+ "_id": 0
24
+ }
25
+ return await Mongo().aggregate('zcbot_platforms', [
26
+ {
27
+ '$lookup': {
28
+ 'from': 'zcbot_auth_user_spider_group',
29
+ 'localField': '_id',
30
+ 'foreignField': 'platCode',
31
+ 'as': 'spider'
32
+ }
33
+ },
34
+ {
35
+ '$match': {'spider.groupCode': group_code}
36
+ },
37
+ {
38
+ '$project': {'spider': 0}
39
+ },
40
+ {'$sort': {'sort': 1}}
41
+ ])
42
+
43
+
44
+ # 根据爬虫组编号,获取可选的爬虫清单
45
+ async def get_spider_group(tenant_code: str = None, group_code: str = None, plat_code: str = None, enable: int = None):
46
+ _query = {}
47
+ if tenant_code:
48
+ _query["_id"] = f'{tenant_code}:{group_code}:{plat_code}:group'
49
+ if group_code:
50
+ _query["groupCode"] = group_code
51
+ if plat_code:
52
+ _query["platCode"] = plat_code
53
+ if enable is not None:
54
+ _query["enable"] = enable
55
+
56
+ return await Mongo().get('zcbot_auth_user_spider_group', query=_query)
57
+
58
+
59
+ # 根据爬虫组编号,获取爬虫组清单
60
+ async def get_spider_group_list(group_code: str = None, plat_codes: List[str] = None, enable: int = None):
61
+ _query = {}
62
+ if group_code:
63
+ _query["groupCode"] = group_code
64
+ if plat_codes and len(plat_codes):
65
+ _query["platCode"] = {"$in": plat_codes}
66
+ if enable is not None:
67
+ _query["enable"] = enable
68
+
69
+ return await Mongo().list('zcbot_auth_user_spider_group', query=_query)
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Optional
3
+ from ..client.mongo_client import Mongo
4
+ from ..model.entity import BatchSpider
5
+ from ..model.enums import CommonStatus
6
+
7
+
8
+ def _build_task_group_key(task_group, plat_code):
9
+ return {'_id': f'{task_group}:{plat_code}:group'}
10
+
11
+
12
+ def _build_stream_spider_key(task_type, plat_code):
13
+ return f'{task_type}:{plat_code}'
14
+
15
+
16
+ # 获取爬虫任务组配置
17
+ async def get_spider_group(task_group, plat_code):
18
+ return await Mongo().get('zcbot_batch_spider_group', _build_task_group_key(task_group, plat_code))
19
+
20
+
21
+ # 获取portainer爬虫配置
22
+ async def get_batch_spider(spider_id: str) -> Optional[BatchSpider]:
23
+ row = await Mongo().get('zcbot_batch_spider', {'spiderId': spider_id, 'status': CommonStatus.ON.name})
24
+ if not row:
25
+ return None
26
+ return BatchSpider(**row)
27
+
28
+
29
+ # 获取支持网站平台
30
+ async def get_platforms_by_spider_group(task_type: str):
31
+ return await Mongo().aggregate('zcbot_platforms', [
32
+ {
33
+ '$lookup': {
34
+ 'from': 'zcbot_batch_spider_group',
35
+ 'localField': '_id',
36
+ 'foreignField': 'plat_code',
37
+ 'as': 'spider'
38
+ }
39
+ },
40
+ {
41
+ '$match': {'spider.task_type': task_type.lower()}
42
+ },
43
+ {
44
+ '$project': {'spider': 0}
45
+ },
46
+ {'$sort': {'sort': 1}}
47
+ ])
@@ -0,0 +1,67 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import List
3
+ from ..client.mongo_client import Mongo
4
+
5
+
6
+ # 获取支持网站平台
7
+ async def get_platforms_by_group(group_code: str, enable: int = None):
8
+ _query = {}
9
+ if group_code:
10
+ _query["groupCode"] = group_code
11
+ if enable is not None:
12
+ _query["enable"] = enable
13
+
14
+ return await Mongo().list('zcbot_batch_spider_group', query=_query)
15
+
16
+
17
+ async def get_platforms_by_group_code(group_code: str, enable):
18
+ _query = {
19
+ "groupCode": group_code
20
+ }
21
+ _fields = {
22
+ "spiders": 0,
23
+ "_id": 0
24
+ }
25
+ return await Mongo().aggregate('zcbot_platforms', [
26
+ {
27
+ '$lookup': {
28
+ 'from': 'zcbot_batch_spider_group',
29
+ 'localField': '_id',
30
+ 'foreignField': 'platCode',
31
+ 'as': 'spider'
32
+ }
33
+ },
34
+ {
35
+ '$match': {'spider.groupCode': group_code}
36
+ },
37
+ {
38
+ '$project': {'spider': 0}
39
+ },
40
+ {'$sort': {'sort': 1}}
41
+ ])
42
+
43
+
44
+ # 根据爬虫组编号,获取可选的爬虫清单
45
+ async def get_spider_group(group_code: str = None, plat_code: str = None, enable: int = None):
46
+ _query = {}
47
+ if group_code:
48
+ _query["groupCode"] = group_code
49
+ if plat_code:
50
+ _query["platCode"] = plat_code
51
+ if enable is not None:
52
+ _query["enable"] = enable
53
+
54
+ return await Mongo().get('zcbot_batch_spider_group', query=_query)
55
+
56
+
57
+ # 根据爬虫组编号,获取爬虫组清单
58
+ async def get_spider_group_list(group_code: str = None, plat_codes: List[str] = None, enable: int = None):
59
+ _query = {}
60
+ if group_code:
61
+ _query["groupCode"] = group_code
62
+ if plat_codes and len(plat_codes):
63
+ _query["platCode"] = {"$in": plat_codes}
64
+ if enable is not None:
65
+ _query["enable"] = enable
66
+
67
+ return await Mongo().list('zcbot_batch_spider_group', query=_query)
@@ -0,0 +1,32 @@
1
+ # -*- coding: utf-8 -*-
2
+ from ..client.mongo_client import Mongo
3
+ from ..model.base import Rule
4
+ from ..client.redis_client import Redis
5
+
6
+
7
+ # 获取链接分拣规则配置
8
+ async def get_url_parse_rule(host: str = None):
9
+ if host:
10
+ return Rule(**await Mongo().get(collection='zcbot_url_parse_rule', query={'_id': host}))
11
+
12
+ return [Rule(**x) for x in await Mongo().list(collection='zcbot_url_parse_rule')]
13
+
14
+
15
+ # 获取支持网站平台
16
+ async def get_platforms():
17
+ return await Mongo().list(collection='zcbot_platforms', sort=[('sort', 1)])
18
+
19
+
20
+ # 获取文件命名规则配置
21
+ async def get_file_name_config(config_id):
22
+ return await Mongo().get(collection='zcbot_file_name_config', query={'_id': config_id})
23
+
24
+
25
+ def create_pipeline():
26
+ pipe = Redis().client.pipeline()
27
+ return pipe
28
+
29
+
30
+ async def run_pipeline(pipe):
31
+ await pipe.execute()
32
+ del pipe
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Optional, List
3
+ from ..client.mongo_client import Mongo
4
+ from ..model.entity import PortainerNode
5
+ from ..model.enums import CommonStatus
6
+
7
+
8
+ # 获取节点信息
9
+ async def get_node(node_id) -> Optional[PortainerNode]:
10
+ rs = await Mongo().get(collection='zcbot_portainer_node', query={'_id': node_id})
11
+ if not rs:
12
+ return None
13
+
14
+ return PortainerNode(**rs)
15
+
16
+
17
+ # 获取节点信息列表
18
+ async def get_node_list(query: dict = None, fields: dict = None, include_disable: bool = False) -> List[PortainerNode]:
19
+ _query = query or {}
20
+ _fields = fields or {}
21
+ if not include_disable:
22
+ _query['status'] = CommonStatus.ON.name
23
+ rows = await Mongo().list(collection='zcbot_portainer_node', query=_query, fields=_fields)
24
+ if rows:
25
+ return [PortainerNode(**row) for row in rows]
26
+
27
+ return []
@@ -0,0 +1,58 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Optional, List
3
+ from ..client.mongo_client import Mongo
4
+ from ..model.entity import BatchSpider
5
+ from ..model.enums import CommonStatus
6
+
7
+
8
+ def _build_task_group_key(task_group, plat_code):
9
+ return {'_id': f'{task_group}:{plat_code}:group'}
10
+
11
+
12
+ def _build_stream_spider_key(task_type, plat_code):
13
+ return f'{task_type}:{plat_code}'
14
+
15
+
16
+ # 获取爬虫任务组配置
17
+ async def get_spider_group(task_group, plat_code):
18
+ return await Mongo().get('zcbot_spider_group', _build_task_group_key(task_group, plat_code))
19
+
20
+
21
+ # 获取portainer爬虫配置
22
+ async def get_spider(spider_id: str, status: CommonStatus = CommonStatus.ON) -> Optional[BatchSpider]:
23
+ row = await Mongo().get('zcbot_spider', {'spiderId': spider_id, 'status': status.name})
24
+ if not row:
25
+ return None
26
+ return BatchSpider(**row)
27
+
28
+
29
+ # 获取支持网站平台
30
+ async def get_platforms_by_spider_group(task_type: str):
31
+ return await Mongo().aggregate('zcbot_platforms', [
32
+ {
33
+ '$lookup': {
34
+ 'from': 'zcbot_spider_group',
35
+ 'localField': '_id',
36
+ 'foreignField': 'plat_code',
37
+ 'as': 'spider'
38
+ }
39
+ },
40
+ {
41
+ '$match': {'spider.task_type': task_type.lower()}
42
+ },
43
+ {
44
+ '$project': {'spider': 0}
45
+ },
46
+ {'$sort': {'sort': 1}}
47
+ ])
48
+
49
+
50
+ async def get_spiders_by_id(spider_ids: List):
51
+ _query = {
52
+ "_id": {
53
+ "$in": spider_ids
54
+ },
55
+ "status": "ON"
56
+ }
57
+ rs = await Mongo().list("zcbot_spider", query=_query)
58
+ return rs
@@ -0,0 +1,67 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import List
3
+ from ..client.mongo_client import Mongo
4
+
5
+
6
+ # 获取支持网站平台
7
+ async def get_platforms_by_group(group_code: str, enable: int = None):
8
+ _query = {}
9
+ if group_code:
10
+ _query["groupCode"] = group_code
11
+ if enable is not None:
12
+ _query["enable"] = enable
13
+
14
+ return await Mongo().list('zcbot_spider_group', query=_query)
15
+
16
+
17
+ async def get_platforms_by_group_code(group_code: str, enable):
18
+ _query = {
19
+ "groupCode": group_code
20
+ }
21
+ _fields = {
22
+ "spiders": 0,
23
+ "_id": 0
24
+ }
25
+ return await Mongo().aggregate('zcbot_platforms', [
26
+ {
27
+ '$lookup': {
28
+ 'from': 'zcbot_spider_group',
29
+ 'localField': '_id',
30
+ 'foreignField': 'platCode',
31
+ 'as': 'spider'
32
+ }
33
+ },
34
+ {
35
+ '$match': {'spider.groupCode': group_code}
36
+ },
37
+ {
38
+ '$project': {'spider': 0}
39
+ },
40
+ {'$sort': {'sort': 1}}
41
+ ])
42
+
43
+
44
+ # 根据爬虫组编号,获取可选的爬虫清单
45
+ async def get_spider_group(group_code: str = None, plat_code: str = None, enable: int = None):
46
+ _query = {}
47
+ if group_code:
48
+ _query["groupCode"] = group_code
49
+ if plat_code:
50
+ _query["platCode"] = plat_code
51
+ if enable is not None:
52
+ _query["enable"] = enable
53
+
54
+ return await Mongo().get('zcbot_spider_group', query=_query)
55
+
56
+
57
+ # 根据爬虫组编号,获取爬虫组清单
58
+ async def get_spider_group_list(group_code: str = None, plat_codes: List[str] = None, enable: int = None):
59
+ _query = {}
60
+ if group_code:
61
+ _query["groupCode"] = group_code
62
+ if plat_codes and len(plat_codes):
63
+ _query["platCode"] = {"$in": plat_codes}
64
+ if enable is not None:
65
+ _query["enable"] = enable
66
+
67
+ return await Mongo().list('zcbot_spider_group', query=_query)
@@ -0,0 +1,41 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Optional, List
3
+ from ..client.mongo_client import Mongo
4
+ from ..model.entity import StreamSpider, StreamSpiderModel
5
+ from ..model.enums import CommonStatus
6
+
7
+
8
+ # 获取portainer爬虫配置
9
+ async def get_stream_spiders(spider_ids: List[str], status: CommonStatus) -> List[StreamSpider]:
10
+ rows = await Mongo().list("zcbot_stream_spider", {'spiderId': {'$in': spider_ids}, 'status': status.name})
11
+ if not rows:
12
+ return []
13
+ return [StreamSpider(**x) for x in rows]
14
+
15
+
16
+ async def get_stream_spider(spider_id: str, status: CommonStatus) -> Optional[StreamSpiderModel]:
17
+ row = await Mongo().get('zcbot_stream_spider', {'spiderId': spider_id, 'status': status.name})
18
+ if not row:
19
+ return None
20
+ return StreamSpiderModel(**row)
21
+
22
+
23
+ # 获取支持网站平台
24
+ async def get_platforms_by_spider_id(spider_ids: List[str], status: CommonStatus):
25
+ return await Mongo().aggregate('zcbot_platforms', [
26
+ {
27
+ '$lookup': {
28
+ 'from': 'zcbot_stream_spider',
29
+ 'localField': '_id',
30
+ 'foreignField': 'plat_code',
31
+ 'as': 'spider'
32
+ }
33
+ },
34
+ {
35
+ '$match': {'spider._id': {'$in': spider_ids}, 'status': status.name}
36
+ },
37
+ {
38
+ '$project': {'spider': 0}
39
+ },
40
+ {'$sort': {'sort': 1}}
41
+ ])