CoolBotDataSys/scripts/crown_extract_incremental.py

179 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""
冠字号增量提取脚本 - 只提取新增帖子的藏品数据
"""
import sys
sys.path.insert(0, '/root/coolbot-data')
import re, psycopg2
from datetime import datetime
DB_CONFIG = {
'host': 'pgm-bp1t1008h019ez6c.pg.rds.aliyuncs.com',
'port': 5432,
'database': 'coolbot_data',
'user': 'coolbot',
'password': 'Coolbot123'
}
FEATURE_KEYWORDS = [
'无47', '无34', '无347', '无4', '无3', '无2',
'标十', '标百', '标九', '标准十', '标准百',
'首日', '生日', '金马', '银马',
'金钩', '倒置', '满号', '圆圆',
'豹子', '顺子', '恐龙', '天龙',
'PMG', '爱藏', '尾号',
'大象', '麒麟', '老虎', '狮子',
'金马王', '天马', '龙马精神',
'连号', '散号', '一刀', '龙凤', '熊猫',
]
def is_date_code(code):
if len(code) != 8:
return False
try:
year = int(code[:4])
month = int(code[4:6])
day = int(code[6:8])
if 2000 <= year <= 2030 and 1 <= month <= 12 and 1 <= day <= 31:
return True
except:
pass
return False
def is_phone(code):
return len(code) == 11 and code.startswith('1')
def is_valid_crown(code):
if not code:
return False
if code.startswith('J0'):
return len(code) in (10, 11)
if len(code) not in (8, 9):
return False
if is_phone(code):
return False
if len(code) == 8 and is_date_code(code):
return False
return True
def extract_codes(text):
if not text:
return set()
codes = set()
for p in [r'J0\d{8}', r'J0\d{9}']:
codes.update(re.findall(p, text))
for c in re.findall(r'\b\d{8}\b', text):
if is_valid_crown(c):
codes.add(c)
for c in re.findall(r'\b\d{9}\b', text):
if is_valid_crown(c):
codes.add(c)
return codes
def extract_features(text):
if not text:
return None
feat = [kw for kw in FEATURE_KEYWORDS if kw in text]
return '|'.join(feat) if feat else None
def extract_price(text):
if not text:
return None, ''
prices = []
for p in [r'(\d+(?:\.\d+)?)\s*元', r'(\d+(?:\.\d+)?)\s*/\s*[张件组百]']:
for x in re.findall(p, text):
try:
v = float(x)
if 1 <= v < 100000:
prices.append(v)
except:
pass
return (min(prices), '') if prices else (None, '')
def get_category(title):
if not title:
return '其他'
for kw in ['', '龙钞', '小龙钞', '钞王']:
if kw in title:
return '龙钞'
for kw in ['', '马钞']:
if kw in title:
return '马钞'
for kw in ['', '蛇钞']:
if kw in title:
return '蛇钞'
return '其他'
def main():
print(f'[{datetime.now()}] 冠字号增量提取开始...')
conn = psycopg2.connect(**DB_CONFIG)
cur = conn.cursor()
# 增量:只选还没有在 collections 表中的帖子
cur.execute("""
SELECT id, post_id, title, content, post_type,
author_username, price, price_unit, url, crawled_at
FROM yichens_posts
WHERE category IN ('龙钞', '马钞', '蛇钞', '其他')
AND id NOT IN (
SELECT DISTINCT CAST(post_id AS INTEGER)
FROM collections
WHERE post_id IS NOT NULL
)
ORDER BY id
LIMIT 500
""")
posts = cur.fetchall()
print(f'待处理新帖子: {len(posts)}')
new_count = 0
skip_count = 0
for (pid, post_id, title, content, post_type,
author, price, price_unit, url, crawled_at) in posts:
text = f'{title or ""} {content or ""}'
codes = extract_codes(text)
if not codes:
skip_count += 1
continue
features = extract_features(text)
price_val, _ = extract_price(text)
price_val = price_val if price_val else price
category = get_category(title)
for code in codes:
try:
cur.execute("""
INSERT INTO collections (
name, crown_code, category, post_id, post_url,
author, price, price_unit,
number_feature, post_title, post_type,
post_crawled_at, created_at, updated_at
) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,NOW(),NOW())
ON CONFLICT (post_id, crown_code) DO NOTHING
""", (
code, code, category, str(post_id), url,
author, price_val, price_unit or '',
features, title, post_type,
crawled_at
))
if cur.rowcount > 0:
new_count += 1
except Exception as e:
print(f' 插入失败 post_id={post_id}, code={code}: {e}')
conn.commit()
total = new_count + skip_count
print(f'完成!新增: {new_count} 条, 无冠号跳过: {skip_count} 条, 总处理: {total}')
cur.execute('SELECT COUNT(*) FROM collections')
print(f'collections表当前总量: {cur.fetchone()[0]}')
conn.close()
if __name__ == '__main__':
main()