File size: 4,987 Bytes
300df0f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import pandas as pd
import os
import json
import time
import logging
import sys

# Thêm thư mục gốc vào path để import được crawler
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from scripts.crawl_thuvienphapluat import ThuVienPhapLuatCrawler

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def find_and_fill_missing_content():
    JSON_INPUT = "chu_de_lao_dong_schema_with_ids.json"
    CONTENT_PARQUET = "data/content_clean.parquet"
    
    if not os.path.exists(JSON_INPUT):
        logger.error(f"❌ Input JSON không tìm thấy: {JSON_INPUT}")
        return

    logger.info(f"📖 Đang đọc danh sách văn bản mục tiêu từ {JSON_INPUT}...")
    with open(JSON_INPUT, "r", encoding="utf-8") as f:
        categories = json.load(f)
    
    targets = []
    for cat in categories:
        for doc in cat.get("van_ban", []):
            if doc.get("doc_id") and doc.get("so_hieu"):
                targets.append({
                    "id": str(doc["doc_id"]),
                    "so_ky_hieu": doc["so_hieu"],
                    "ten": doc.get("ten", "")
                })
    
    logger.info(f"📊 Tổng số văn bản mục tiêu từ JSON: {len(targets)}")

    if not os.path.exists(CONTENT_PARQUET):
        logger.warning(f"⚠️ {CONTENT_PARQUET} không tồn tại. Sẽ tạo mới.")
        content_df = pd.DataFrame(columns=["id", "clean_html"])
    else:
        logger.info(f"📖 Đang tải nội dung hiện có từ {CONTENT_PARQUET}...")
        content_df = pd.read_parquet(CONTENT_PARQUET)
        content_df["id"] = content_df["id"].astype(str)

    # Tìm các văn bản bị thiếu hoặc nội dung quá ngắn
    existing_ids = set(content_df["id"].tolist())
    
    short_content_ids = set()
    if not content_df.empty:
        # Lọc các id có độ dài html < 500
        short_content_ids = set(content_df[content_df["clean_html"].str.len() < 500]["id"].tolist())

    missing_targets = []
    for t in targets:
        if t["id"] not in existing_ids or t["id"] in short_content_ids:
            missing_targets.append(t)

    logger.info(f"🎯 Tìm thấy {len(missing_targets)} văn bản bị thiếu hoặc nội dung ngắn (< 500 ký tự).")

    if not missing_targets:
        logger.info("✅ Không có nội dung nào bị thiếu. Hệ thống đã đầy đủ!")
        return

    # Bắt đầu crawl
    crawler = ThuVienPhapLuatCrawler()
    new_contents = []
    
    try:
        for i, target in enumerate(missing_targets):
            logger.info(f"[{i+1}/{len(missing_targets)}] Đang xử lý: {target['ten']} ({target['so_ky_hieu']})")
            
            # Tìm kiếm URL
            urls = crawler.search_documents(target["so_ky_hieu"])
            if not urls:
                logger.warning(f"  ❌ Không tìm thấy URL cho số hiệu {target['so_ky_hieu']}")
                continue
                
            # Lấy URL đầu tiên
            url = urls[0]
            if not url.startswith("http"):
                url = "https://thuvienphapluat.vn" + url
                
            html = crawler.scrape_content_only(url)
            
            if html and len(html) > 500:
                new_contents.append({"id": target["id"], "clean_html": html})
                logger.info(f"  ✅ Đã lấy được nội dung ({len(html)} ký tự)")
            else:
                logger.warning(f"  ⚠️ Nội dung lấy về vẫn quá ngắn hoặc rỗng cho {target['so_ky_hieu']}")
            
            # Chờ 2 giây sau mỗi văn bản theo yêu cầu
            time.sleep(2)
            
            # Lưu checkpoint mỗi 10 văn bản để tránh mất dữ liệu nếu crash
            if (i + 1) % 10 == 0 and new_contents:
                logger.info(f"💾 Đang lưu checkpoint vào {CONTENT_PARQUET}...")
                new_df = pd.DataFrame(new_contents)
                content_df = pd.concat([content_df, new_df]).drop_duplicates(subset=["id"], keep="last")
                content_df.to_parquet(CONTENT_PARQUET, index=False)
                new_contents = []

    except KeyboardInterrupt:
        logger.info("🛑 Đã dừng theo yêu cầu người dùng. Đang lưu kết quả hiện tại...")
    except Exception as e:
        logger.error(f"💥 Lỗi nghiêm trọng: {e}")
    finally:
        if new_contents:
            logger.info(f"💾 Đang lưu kết quả cuối cùng vào {CONTENT_PARQUET}...")
            new_df = pd.DataFrame(new_contents)
            content_df = pd.concat([content_df, new_df]).drop_duplicates(subset=["id"], keep="last")
            content_df.to_parquet(CONTENT_PARQUET, index=False)
            logger.info(f"✅ Đã cập nhật {CONTENT_PARQUET}. Tổng số văn bản: {len(content_df)}")

if __name__ == "__main__":
    find_and_fill_missing_content()