File size: 6,263 Bytes
398a289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import argparse
import json
import os
import sys
import time

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from src.data_process.crawlers.crawl_fb import group_post_scraper_v2, post_scraper
from src.data_process.crawlers.crawl_fb.group_post_scraper_v2 import (
    fetch_posts as fetch_group_posts,
)
from src.data_process.crawlers.crawl_fb.main import (
    extract_group_id_from_url,
    extract_user_id_from_url,
)
from src.data_process.crawlers.crawl_fb.post_scraper import (
    fetch_posts as fetch_page_posts,
)
from src.models.fusion_inference import verify_claims_true_false


def crawl_page_posts(url: str, count: int, min_comments: int = 0):
    """
    Cào bài viết từ một trang cá nhân (page/profile).
    """
    print(f"\n[Page] {url}")
    page_id = extract_user_id_from_url(url)
    if not page_id:
        print("  ✗ Không lấy được Page ID từ URL")
        return

    print(f"  Page ID: {page_id}")
    post_scraper.USER_ID = page_id
    post_scraper.BASE_HEADERS["referer"] = (
        f"https://www.facebook.com/profile.php?id={page_id}"
    )

    all_posts_data = []

    def process_batch(batch_posts, total_so_far, total_limit):
        print(
            f"  Đang xử lý batch {len(batch_posts)} bài ({total_so_far}/{total_limit})..."
        )
        for j, post in enumerate(batch_posts, 1):
            post_id = post.get("post_id")
            if not post_id:
                continue
            print(f"    [{j}] Post {post_id}...")
            filtered_post = {
                "post_id": post.get("post_id"),
                "message": post.get("message"),
                "comment_count": post.get("comment_count"),
                "group_name": post.get("group_name"),
            }
            all_posts_data.append(filtered_post)
            print("✓ Đã lấy dữ liệu")
            time.sleep(1)

    print(f"  Đang tải {count} bài viết...")
    try:
        posts = fetch_page_posts(
            count, min_comments, batch_size=2, on_batch_complete=process_batch
        )
        print(f"  ✓ Hoàn thành: {len(posts)} bài")

        return all_posts_data
    except Exception as e:
        print(f"  ✗ Lỗi: {e}")


def crawl_group_posts(url: str, count: int, min_comments: int = 0):
    """
    Cào bài viết từ một nhóm (group).
    """
    print(f"\n[Group] {url}")
    group_id = extract_group_id_from_url(url)
    if not group_id:
        print("  ✗ Không lấy được Group ID từ URL")
        return

    print(f"  Group ID: {group_id}")
    group_post_scraper_v2.GROUP_ID = group_id
    group_post_scraper_v2.HEADERS["referer"] = (
        f"https://www.facebook.com/groups/{group_id}/"
    )

    all_posts_data = []

    def process_batch(batch_posts, total_so_far, total_limit):
        print(
            f"  Đang xử lý batch {len(batch_posts)} bài ({total_so_far}/{total_limit})..."
        )
        for j, post in enumerate(batch_posts, 1):
            post_id = post.get("post_id")
            if not post_id:
                continue
            print(f"    [{j}] Post {post_id}...")
            filtered_post = {
                "post_id": post.get("post_id"),
                "message": post.get("message"),
                "comment_count": post.get("comment_count"),
                "group_name": post.get("group_name"),
            }
            all_posts_data.append(filtered_post)
            print("      ✓ Đã lấy dữ liệu")
            time.sleep(1)

    print(f"  Đang tải {count} bài viết...")
    try:
        posts = fetch_group_posts(
            count, min_comments, batch_size=2, on_batch_complete=process_batch
        )
        print(f"  ✓ Hoàn thành: {len(posts)} bài")

        return all_posts_data
    except Exception as e:
        print(f"  ✗ Lỗi: {e}")


def crawl_from_file(file_path: str, count: int, min_comments: int = 0):
    """
    Đọc danh sách link từ file txt và chạy crawl cho từng link.
    """
    print(f"\n[File] Đọc danh sách link từ: {file_path}")
    try:
        with open(file_path, "r", encoding="utf-8") as f:
            links = [line.strip() for line in f if line.strip()]
    except Exception as e:
        print(f"  ✗ Không thể đọc file {file_path}: {e}")
        return

    print(f"  Tìm thấy {len(links)} link.")
    for i, link in enumerate(links, 1):
        print(f"\n--- Đang xử lý link {i}/{len(links)} ---")
        if "/groups/" in link or "/group/" in link:
            groups = crawl_group_posts(link, count, min_comments)
        else:
            pages = crawl_page_posts(link, count, min_comments)
    return pages + groups


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Facebook Scraper bằng dòng lệnh (CLI)"
    )
    parser.add_argument("--url", help="URL của trang, nhóm hoặc đường dẫn file .txt")
    parser.add_argument(
        "--count", type=int, default=5, help="Số lượng bài viết tối đa cần lấy"
    )
    parser.add_argument(
        "--min_comments",
        type=int,
        default=0,
        help="Số lượng bình luận tối thiểu cần cho mỗi bài",
    )
    args = parser.parse_args()
    if not args.url:
        print(
            "Lỗi: Bạn cần cung cấp URL (trang, nhóm) hoặc file .txt thông qua tham số --url."
        )
        sys.exit(1)

    posts = crawl_from_file(args.url, args.count, args.min_comments)
    if not posts:
        print(
            "Không có bài viết nào được tìm thấy để kiểm chứng hoặc file không hợp lệ."
        )
        sys.exit(1)

    texts = [post["message"] for post in posts]
    results = verify_claims_true_false(
        claims=texts,
        fusion_model_path="models/fusion_model.pt",
        llm_model_path="models/lora_llm",
        retriever_model_path="AITeamVN/Vietnamese_Embedding",
        opensearch_index="news_kb",
        llm_evidence_top_k=5,
        debug=True,
    )
    for post, result in zip(posts, results):
        post["result"] = result
    # save json file
    with open("posts.json", "w", encoding="utf-8") as f:
        json.dump(posts, f, ensure_ascii=False, indent=4)