Download app.py from bep40/fb-comments-crawler-space: direct link, hf CLI and curl.
- Browser
- Download file 5.23 kB
-
https://huggingface.co/spaces/bep40/fb-comments-crawler-space/resolve/main/app.py
- Command line
-
hf download hf://spaces/bep40/fb-comments-crawler-space/app.py
-
curl -L -o app.py https://huggingface.co/spaces/bep40/fb-comments-crawler-space/resolve/main/app.py
5.23 kB
| """FB Comments Crawler β Gradio Space UI. | |
| Crawl 100% of comments (with pagination + replies) from a Facebook post you | |
| have permission to read (see README), and download CSV/JSON with commenter UID. | |
| The OAuth login step (getting a Page access token) must be done on your local | |
| machine because Facebook redirects the browser to localhost. This Space accepts | |
| the token you already have and does the crawling. | |
| """ | |
| import json | |
| import os | |
| import tempfile | |
| from pathlib import Path | |
| import gradio as gr | |
| import pandas as pd | |
| from fb_comments import ( | |
| CommentCrawler, | |
| CommentCrawlerError, | |
| RateLimitError, | |
| parse_post_identifier, | |
| resolve_post_id, | |
| ) | |
| # --------------------------------------------------------------------------- # | |
| # Crawl logic | |
| # --------------------------------------------------------------------------- # | |
| def crawl(token: str, url_or_id: str, include_replies: bool): | |
| """Run the crawl; return (csv_path, json_path, df, status_text).""" | |
| token = (token or "").strip() | |
| url_or_id = (url_or_id or "").strip() | |
| if not token: | |
| return None, None, None, "β Token requi. Get a Page access token first (see tab Help)." | |
| if not url_or_id: | |
| return None, None, None, "β Post URL/id requi." | |
| try: | |
| post_id = parse_post_identifier(url_or_id) | |
| except Exception as e: | |
| return None, None, None, f"β Invalid post URL/id: {e}" | |
| cc = CommentCrawler(token) | |
| try: | |
| post_id = resolve_post_id(post_id, cc) | |
| except Exception: | |
| pass | |
| try: | |
| comments = list(cc.comments(post_id, include_replies=bool(include_replies))) | |
| except RateLimitError as e: | |
| return None, None, None, f"β Rate limited: {e}" | |
| except CommentCrawlerError as e: | |
| return None, None, None, f"β API error: {e} β verify token is a Page token of a page you manage." | |
| except Exception as e: | |
| return None, None, None, f"β Unexpected: {e}" | |
| if not comments: | |
| return None, None, None, "No comments (or post not readable with this token)." | |
| rows = [] | |
| for c in comments: | |
| author = c.get("from") or {} | |
| rows.append({ | |
| "comment_id": c.get("id"), | |
| "parent_id": (c.get("parent") or {}).get("id"), | |
| "name": author.get("name"), | |
| "uid": author.get("id"), | |
| "message": c.get("message") or "", | |
| "created_time": c.get("created_time"), | |
| "like_count": c.get("like_count"), | |
| }) | |
| df = pd.DataFrame(rows) | |
| out_dir = tempfile.gettempdir() | |
| base = f"comments_{len(rows)}" | |
| csv_path = str(Path(out_dir) / f"{base}.csv") | |
| json_path = str(Path(out_dir) / f"{base}.json") | |
| df.to_csv(csv_path, index=False, encoding="utf-8-sig") | |
| with open(json_path, "w", encoding="utf-8") as fh: | |
| json.dump(rows, fh, ensure_ascii=False, indent=2) | |
| return csv_path, json_path, df, f"OK: {len(rows)} comments (top-level + replies) collected." | |
| # --------------------------------------------------------------------------- # | |
| # Help text | |
| # --------------------------------------------------------------------------- # | |
| HELP = """ | |
| ### How to get a Page access token | |
| 1. Create a FB app at developers.facebook.com/apps β **Facebook Login**, keep **Development** mode. | |
| 2. Add `http://localhost:8080/callback` to **Valid OAuth Redirect URIs** + enable Web OAuth. | |
| 3. Add your account as **Admin** under Roles. (No App Review needed for pages you own.) | |
| 4. On your own machine run: | |
| ``` | |
| pip install . # install fb-comments-crawler | |
| fbcomments login --app-id <APP_ID> --app-secret <SECRET> --port 8080 | |
| ``` | |
| β open the printed URL, log in as page admin β token saved to `token.json`. | |
| 5. Paste the `page_access_token` value into the box here. | |
| > You can only read comments on posts of **Pages you manage** (permission | |
| > `pages_read_engagement`). Posts of other pages return error #283. | |
| The **uid** column holds the **PSID** (Page-Scoped user ID) β the modern stable FB user identifier. | |
| """ | |
| # --------------------------------------------------------------------------- # | |
| # Gradio UI | |
| # --------------------------------------------------------------------------- # | |
| with gr.Blocks(title="FB Comments Crawler") as demo: | |
| gr.Markdown("# FB Comments Crawler\nPull 100% of comments (with UID) from a FB post you manage, download CSV/JSON.") | |
| with gr.Tab("Crawl"): | |
| token = gr.Textbox(label="Page access token", type="password", | |
| placeholder="EAAG... paste token from token.json") | |
| url = gr.Textbox(label="Post URL or id", | |
| placeholder="https://www.facebook.com/MyPage/posts/pfbid0...") | |
| replies = gr.Checkbox(label="Include reply comments", value=True) | |
| btn = gr.Button("Crawl", variant="primary") | |
| status = gr.Markdown("Ready.") | |
| df_out = gr.Dataframe(label="Comments preview") | |
| csv_file = gr.File(label="Download CSV") | |
| json_file = gr.File(label="Download JSON") | |
| btn.click(fn=crawl, inputs=[token, url, replies], | |
| outputs=[csv_file, json_file, df_out, status]) | |
| with gr.Tab("Help"): | |
| gr.Markdown(HELP) | |
| demo.queue() | |
| if __name__ == "__main__": | |
| demo.launch() |