|
@@ -8,16 +8,13 @@ import time
|
|
|
from datetime import datetime
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
import requests
|
|
import requests
|
|
|
-
|
|
|
|
|
|
|
+from commons.scheduler import CrawlerScheduler
|
|
|
from commons.Logger import get_spider_logger
|
|
from commons.Logger import get_spider_logger
|
|
|
from commons.feishu_webhook import send_text, send_error_card
|
|
from commons.feishu_webhook import send_text, send_error_card
|
|
|
from spiders.yaoex.yaoex_crawl import (
|
|
from spiders.yaoex.yaoex_crawl import (
|
|
|
YaoexCrawler,
|
|
YaoexCrawler,
|
|
|
PLATFORM_ID,
|
|
PLATFORM_ID,
|
|
|
YYC_DEVICE_ID,
|
|
YYC_DEVICE_ID,
|
|
|
- TASK_PULL_URL,
|
|
|
|
|
- TASK_HEARTBEAT_URL,
|
|
|
|
|
- TASK_API_TOKEN,
|
|
|
|
|
)
|
|
)
|
|
|
from spiders.yaoex.yaoex_snapshot_crawl import YaoexSnapshotCrawl
|
|
from spiders.yaoex.yaoex_snapshot_crawl import YaoexSnapshotCrawl
|
|
|
|
|
|
|
@@ -28,42 +25,6 @@ IDLE_SECONDS_MIN = 180
|
|
|
IDLE_SECONDS_MAX = 300
|
|
IDLE_SECONDS_MAX = 300
|
|
|
|
|
|
|
|
|
|
|
|
|
-def pull_task():
|
|
|
|
|
- """从内部调度 API 拉取任务"""
|
|
|
|
|
- headers = {'X-Crawler-Token': TASK_API_TOKEN}
|
|
|
|
|
- params = {'platform': PLATFORM_ID, 'username': YYC_DEVICE_ID}
|
|
|
|
|
- try:
|
|
|
|
|
- response = requests.get(TASK_PULL_URL, params=params, headers=headers, timeout=15)
|
|
|
|
|
- result = response.json()
|
|
|
|
|
- logger.info("拉取任务 API 返回: %s", result)
|
|
|
|
|
- if result.get('code') == 'success':
|
|
|
|
|
- task = result.get('data', {}).get('task') or {}
|
|
|
|
|
- if task and task.get("id"):
|
|
|
|
|
- logger.info("拉取任务成功 platform=%s task_id=%s", PLATFORM_ID, task.get("id"))
|
|
|
|
|
- return task
|
|
|
|
|
- else:
|
|
|
|
|
- logger.info("拉取任务成功但无有效任务(task=%s),视为暂无任务", task)
|
|
|
|
|
- return {}
|
|
|
|
|
- else:
|
|
|
|
|
- logger.warning("拉取任务 API 返回非 success: code=%s, msg=%s",
|
|
|
|
|
- result.get('code'), result.get('msg'))
|
|
|
|
|
- return {}
|
|
|
|
|
- except Exception as e:
|
|
|
|
|
- logger.error("拉取任务 API 请求失败: %s", e)
|
|
|
|
|
- return {}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-def send_heartbeat():
|
|
|
|
|
- """向调度 API 上报心跳,告知服务器爬虫在线"""
|
|
|
|
|
- headers = {'X-Crawler-Token': TASK_API_TOKEN}
|
|
|
|
|
- payload = {"platform": str(PLATFORM_ID), "username": YYC_DEVICE_ID}
|
|
|
|
|
- try:
|
|
|
|
|
- resp = requests.post(TASK_HEARTBEAT_URL, json=payload, headers=headers, timeout=10)
|
|
|
|
|
- logger.debug("心跳上报: HTTP %s, %s", resp.status_code, resp.text[:200])
|
|
|
|
|
- except Exception as e:
|
|
|
|
|
- logger.warning("心跳上报失败: %s", e)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
def notify_result(task, crawl_count, success):
|
|
def notify_result(task, crawl_count, success):
|
|
|
"""发送飞书通知"""
|
|
"""发送飞书通知"""
|
|
|
try:
|
|
try:
|
|
@@ -90,14 +51,22 @@ def notify_result(task, crawl_count, success):
|
|
|
|
|
|
|
|
def main_loop():
|
|
def main_loop():
|
|
|
"""循环拉取任务并执行采集"""
|
|
"""循环拉取任务并执行采集"""
|
|
|
|
|
+ scheduler = CrawlerScheduler(YYC_DEVICE_ID, str(PLATFORM_ID))
|
|
|
idle_seconds = random.randint(IDLE_SECONDS_MIN, IDLE_SECONDS_MAX)
|
|
idle_seconds = random.randint(IDLE_SECONDS_MIN, IDLE_SECONDS_MAX)
|
|
|
logger.info("壹药城采集启动,每轮间隔 %s 秒", idle_seconds)
|
|
logger.info("壹药城采集启动,每轮间隔 %s 秒", idle_seconds)
|
|
|
|
|
|
|
|
while True:
|
|
while True:
|
|
|
try:
|
|
try:
|
|
|
- # 先上报心跳,告诉服务器爬虫在线
|
|
|
|
|
- send_heartbeat()
|
|
|
|
|
- task = pull_task()
|
|
|
|
|
|
|
+ # 先同步心跳确保登记,再启守护线程拉任务
|
|
|
|
|
+ import requests as _r
|
|
|
|
|
+ _r.post(
|
|
|
|
|
+ scheduler.heartbeat_url,
|
|
|
|
|
+ json={"platform": scheduler.platform, "username": scheduler.username},
|
|
|
|
|
+ headers={'X-Crawler-Token': 'zhijiayun_crawler_2026'},
|
|
|
|
|
+ timeout=5
|
|
|
|
|
+ )
|
|
|
|
|
+ scheduler.start()
|
|
|
|
|
+ task = scheduler.get_task() or {}
|
|
|
if not task:
|
|
if not task:
|
|
|
logger.info("%s 暂无任务,等待 %s 秒后重试", PLATFORM_NAME, idle_seconds)
|
|
logger.info("%s 暂无任务,等待 %s 秒后重试", PLATFORM_NAME, idle_seconds)
|
|
|
time.sleep(idle_seconds)
|
|
time.sleep(idle_seconds)
|