Files
ZDXX/2_1banben/services/crawler_82.py
DXC 1412b0ed0b fix: 爬虫不再用运行时刻伪造数据时间
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 决定(离线时冻结上一个有效时间)。
2026-09-15 17:05:31 +08:00

66 lines
2.4 KiB
Python
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.

# 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