crawler_106: - find_closest_item 原来用 abs(now - item) 取“离现在最近”,服务端只要存在 未来日期的目录就会被选中。改为只保留不晚于当前时间的项,再取最新那个。 - 目录名只有日期,按当天 00:00 参与比较。不能用 23:59:59,否则“今天”的目录 会大于当前时刻而被当成未来剔除,永远只取到昨天的数据。 - 文件 modified 带 Z 表示 UTC,不带时区的按东八区补上。原来 .replace(tzinfo=None) 会让 naive/aware 比较抛异常,被 except 静默吞掉,导致所有文件被丢弃。 - target_time 不再用「目录日期 + datetime.now()」拼接(那写进库的是爬虫跑批 时刻,而 calculate_offset 只取日期部分,等于在骗前端)。改为从最终文件路径 正则提取真实记录时间,正则没命中时退化到文件修改时间。 - 正则放宽:兼容 /Data 与 /data、前导斜杠、扩展名大小写。 crawler_82: - 基础数据包的 target_time 默认值不再用 datetime.now()。 - d_list 为空时原为字符串 "N/A",它是真值,会通过入库层的 if target_date 判断,把设备主表已冻结的有效时间覆盖掉。改为 None。 爬虫层只负责解析真实记录时间,解析不出来就留 None;如何入库交给 services/db_ingest 决定(离线时冻结上一个有效时间)。
66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
# services/crawler_82.py
|
||
import requests
|
||
import json
|
||
import logging
|
||
from lxml import etree
|
||
from config import Config
|
||
from datetime import datetime
|
||
|
||
CONFIG = Config.CRAWLER_CONFIG["82"]
|
||
|
||
|
||
def run_82_logic():
|
||
"""返回 result_list"""
|
||
results = []
|
||
print(">>> [82爬虫] 启动...")
|
||
session = requests.Session()
|
||
|
||
try:
|
||
session.post(f"{CONFIG['base_url']}/login.php", data=CONFIG["login"], timeout=10)
|
||
resp = session.post(f"{CONFIG['base_url']}/GetStationList.php", timeout=10)
|
||
html = etree.HTML(resp.content)
|
||
if html is None: return []
|
||
|
||
stations = html.xpath('//option/@value')
|
||
for sid in [s for s in stations if s]:
|
||
data_packet = {
|
||
'source': '82网站',
|
||
'name': str(sid),
|
||
'status': '正常',
|
||
'value': '',
|
||
# 同 106:默认留空,只有真正拿到数据时间才覆盖,
|
||
# 不用 datetime.now() 冒充数据时间
|
||
'target_time': None,
|
||
'raw_json': {},
|
||
'temp_file': None
|
||
}
|
||
try:
|
||
r = session.post(f"{CONFIG['base_url']}/getLastWeatherData.php", data=str(sid),
|
||
headers={'Content-Type': 'text/plain'}, timeout=10)
|
||
try:
|
||
data = r.json()
|
||
except:
|
||
data = None
|
||
|
||
if data:
|
||
d_list = data.get('date', [])
|
||
# 拿不到时间时必须是 None,不能是 "N/A" —— 字符串在入库层是真值,
|
||
# 会把设备主表已经冻结的有效 latest_time 覆盖掉,令 offset 倒退成"从未同步"
|
||
latest = str(d_list[-1]) if d_list else None
|
||
data_packet['target_time'] = latest
|
||
data_packet['value'] = f"Data Points: {len(d_list)}"
|
||
data_packet['raw_json'] = data # 🔥 存完整JSON
|
||
else:
|
||
data_packet['status'] = '异常'
|
||
data_packet['value'] = "返回空数据"
|
||
|
||
except Exception as e:
|
||
data_packet['status'] = '异常'
|
||
data_packet['value'] = "单个采集失败"
|
||
|
||
results.append(data_packet)
|
||
|
||
except Exception as e:
|
||
logging.error(f"82 Crawler Error: {e}")
|
||
|
||
return results |