Refat81 commited on
Commit
e8a2c75
Β·
verified Β·
1 Parent(s): ffc0355

Update pages/facebook_extractor.py

Browse files
Files changed (1) hide show
  1. pages/facebook_extractor.py +475 -19
pages/facebook_extractor.py CHANGED
@@ -1,34 +1,490 @@
1
  # pages/facebook_extractor.py
2
  import streamlit as st
 
 
 
 
 
 
 
3
 
4
- def main():
5
- st.set_page_config(page_title="Facebook Extractor", page_icon="πŸ“˜", layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- st.title("πŸ“˜ Facebook Data Extractor")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  if st.button("← Back to Main Dashboard"):
10
  st.switch_page("app.py")
11
 
12
- st.warning("""
13
- ## ⚠️ Basic Facebook Extractor
14
-
15
- **For enhanced Facebook features, use Facebook Extractor 2.0**
 
 
 
 
 
 
 
16
 
17
- This version provides basic public data extraction.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- **Features available in Facebook Extractor 2.0:**
20
- - Enhanced algorithms
21
- - AI-powered analysis
22
- - Better content recognition
23
- - Advanced chat capabilities
24
- """)
25
 
26
- st.info("""
27
- **Click the button below to access the enhanced version:**
28
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
- if st.button("πŸš€ Switch to Facebook Extractor 2.0", type="primary"):
31
- st.switch_page("pages/facebook_extractor_pro.py")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  if __name__ == "__main__":
34
  main()
 
1
  # pages/facebook_extractor.py
2
  import streamlit as st
3
+ import requests
4
+ from bs4 import BeautifulSoup
5
+ import json
6
+ import re
7
+ from datetime import datetime
8
+ from typing import List, Dict
9
+ import os
10
 
11
+ # Import your existing AI components
12
+ from langchain_text_splitters import CharacterTextSplitter
13
+ from langchain_community.embeddings import HuggingFaceEmbeddings
14
+ from langchain.vectorstores import FAISS
15
+ from langchain.memory import ConversationBufferMemory
16
+ from langchain.chains import ConversationalRetrievalChain
17
+ from langchain.schema import Document
18
+ from langchain_community.llms import HuggingFaceHub
19
+
20
+ st.set_page_config(
21
+ page_title="Facebook Data Extractor",
22
+ page_icon="πŸ“˜",
23
+ layout="wide"
24
+ )
25
+
26
+ class FacebookPublicExtractor:
27
+ """Facebook public data extractor that works on Hugging Face"""
28
+
29
+ def __init__(self):
30
+ self.session = requests.Session()
31
+ self.setup_session()
32
+
33
+ def setup_session(self):
34
+ """Setup requests session with headers"""
35
+ self.session.headers.update({
36
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
37
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
38
+ 'Accept-Language': 'en-US,en;q=0.5',
39
+ 'Accept-Encoding': 'gzip, deflate, br',
40
+ 'DNT': '1',
41
+ 'Connection': 'keep-alive',
42
+ 'Upgrade-Insecure-Requests': '1',
43
+ })
44
+
45
+ def extract_public_data(self, url: str, data_type: str) -> Dict:
46
+ """Extract public data from Facebook URLs"""
47
+ try:
48
+ st.info(f"🌐 Accessing: {url}")
49
+
50
+ # Validate URL type
51
+ url_type = self.analyze_facebook_url(url)
52
+
53
+ response = self.session.get(url, timeout=15)
54
+
55
+ if response.status_code != 200:
56
+ return {
57
+ "error": f"Failed to access page (Status: {response.status_code})",
58
+ "url_type": url_type,
59
+ "status": "error"
60
+ }
61
+
62
+ soup = BeautifulSoup(response.text, 'html.parser')
63
+
64
+ # Remove scripts and styles
65
+ for script in soup(["script", "style", "meta", "link"]):
66
+ script.decompose()
67
+
68
+ # Extract basic information
69
+ text = soup.get_text()
70
+ lines = (line.strip() for line in text.splitlines())
71
+ chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
72
+ clean_text = ' '.join(chunk for chunk in chunks if chunk)
73
+
74
+ # Extract structured data
75
+ page_info = self._extract_page_info(soup, url, response)
76
+ content_blocks = self._extract_content_blocks(clean_text, url_type)
77
+
78
+ return {
79
+ "page_info": page_info,
80
+ "content_blocks": content_blocks,
81
+ "url_type": url_type,
82
+ "extraction_time": datetime.now().isoformat(),
83
+ "data_type": data_type,
84
+ "status": "success"
85
+ }
86
+
87
+ except Exception as e:
88
+ return {"error": f"Extraction failed: {str(e)}", "status": "error"}
89
+
90
+ def analyze_facebook_url(self, url: str) -> str:
91
+ """Analyze Facebook URL type"""
92
+ url_lower = url.lower()
93
+
94
+ if 'facebook.com/groups/' in url_lower:
95
+ return "Facebook Group (Limited public data)"
96
+ elif 'facebook.com/pages/' in url_lower or '/pages/' in url_lower:
97
+ return "Facebook Page (Public data available)"
98
+ elif 'facebook.com/events/' in url_lower:
99
+ return "Facebook Event (Limited access)"
100
+ elif 'facebook.com/marketplace/' in url_lower:
101
+ return "Facebook Marketplace"
102
+ elif 'facebook.com/' in url_lower and '/posts/' in url_lower:
103
+ return "Facebook Post"
104
+ else:
105
+ return "Facebook Profile/Page"
106
+
107
+ def _extract_page_info(self, soup, url: str, response) -> Dict:
108
+ """Extract page information"""
109
+ title = soup.find('title')
110
+ meta_desc = soup.find('meta', attrs={'name': 'description'})
111
+ og_title = soup.find('meta', property='og:title')
112
+ og_description = soup.find('meta', property='og:description')
113
+ og_image = soup.find('meta', property='og:image')
114
+
115
+ return {
116
+ "title": title.text.strip() if title else "Facebook Content",
117
+ "description": meta_desc['content'] if meta_desc else "",
118
+ "og_title": og_title['content'] if og_title else "",
119
+ "og_description": og_description['content'] if og_description else "",
120
+ "og_image": og_image['content'] if og_image else "",
121
+ "url": url,
122
+ "response_code": response.status_code,
123
+ "content_length": len(response.text),
124
+ "access_note": self._get_access_note(soup)
125
+ }
126
+
127
+ def _extract_content_blocks(self, text: str, url_type: str) -> List[Dict]:
128
+ """Extract meaningful content blocks"""
129
+ blocks = []
130
+
131
+ # Split into paragraphs/sentences
132
+ paragraphs = [p.strip() for p in text.split('.') if p.strip() and len(p.strip()) > 20]
133
+
134
+ for i, paragraph in enumerate(paragraphs[:15]): # Limit to first 15
135
+ content_type = self._analyze_content_type(paragraph, url_type)
136
+
137
+ block = {
138
+ "id": i + 1,
139
+ "content": paragraph,
140
+ "length": len(paragraph),
141
+ "word_count": len(paragraph.split()),
142
+ "content_type": content_type,
143
+ "has_links": 'http' in paragraph.lower(),
144
+ "is_public_content": self._is_public_content(paragraph)
145
+ }
146
+ blocks.append(block)
147
+
148
+ return blocks
149
+
150
+ def _analyze_content_type(self, text: str, url_type: str) -> str:
151
+ """Analyze content type"""
152
+ text_lower = text.lower()
153
+
154
+ if any(word in text_lower for word in ['event', 'date', 'time', 'location']):
155
+ return "event_info"
156
+ elif any(word in text_lower for word in ['group', 'community', 'member', 'join']):
157
+ return "community_info"
158
+ elif any(word in text_lower for word in ['marketplace', 'buy', 'sell', 'price']):
159
+ return "commerce"
160
+ elif any(word in text_lower for word in ['post', 'share', 'comment']):
161
+ return "social_content"
162
+ elif any(word in text_lower for word in ['login', 'sign in']):
163
+ return "authentication"
164
+ else:
165
+ return "general_content"
166
+
167
+ def _is_public_content(self, text: str) -> bool:
168
+ """Check if content appears to be publicly accessible"""
169
+ text_lower = text.lower()
170
+ private_indicators = [
171
+ 'log in to see', 'sign up to see', 'you must log in',
172
+ 'private content', 'restricted access'
173
+ ]
174
+
175
+ return not any(indicator in text_lower for indicator in private_indicators)
176
+
177
+ def _get_access_note(self, soup) -> str:
178
+ """Get access level note"""
179
+ page_text = soup.get_text().lower()
180
+
181
+ if any(phrase in page_text for phrase in ['log in', 'sign in', 'you must be logged in']):
182
+ return "Login required for full access"
183
+ elif 'content not available' in page_text:
184
+ return "Content not publicly available"
185
+ else:
186
+ return "Public content accessible"
187
+
188
+ # AI Functions (same as your LinkedIn analyzer)
189
+ def get_embeddings():
190
+ """Initialize embeddings"""
191
+ try:
192
+ embeddings = HuggingFaceEmbeddings(
193
+ model_name="sentence-transformers/all-MiniLM-L6-v2"
194
+ )
195
+ return embeddings
196
+ except Exception as e:
197
+ st.error(f"Embeddings error: {e}")
198
+ return None
199
+
200
+ def get_llm():
201
+ """Initialize HuggingFace LLM"""
202
+ try:
203
+ api_key = os.getenv('HUGGINGFACEHUB_API_TOKEN')
204
+ if not api_key:
205
+ st.error("HuggingFace API Key not found")
206
+ return None
207
+
208
+ llm = HuggingFaceHub(
209
+ repo_id="mistralai/Mistral-7B-Instruct-v0.1",
210
+ huggingfacehub_api_token=api_key,
211
+ model_kwargs={
212
+ "temperature": 0.7,
213
+ "max_length": 512,
214
+ "max_new_tokens": 256,
215
+ }
216
+ )
217
+ return llm
218
+ except Exception as e:
219
+ st.error(f"LLM error: {e}")
220
+ return None
221
+
222
+ def process_facebook_data(extracted_data):
223
+ """Process extracted data for AI analysis"""
224
+ if not extracted_data or extracted_data.get("status") != "success":
225
+ return None, []
226
+
227
+ page_info = extracted_data['page_info']
228
+ content_blocks = extracted_data['content_blocks']
229
+ url_type = extracted_data['url_type']
230
+
231
+ all_text = f"FACEBOOK DATA ANALYSIS\n{'='*50}\n\n"
232
+ all_text += f"πŸ“„ PAGE INFORMATION:\n"
233
+ all_text += f"Title: {page_info['title']}\n"
234
+ all_text += f"URL: {page_info['url']}\n"
235
+ all_text += f"URL Type: {url_type}\n"
236
+ all_text += f"Access: {page_info['access_note']}\n"
237
+ all_text += f"Extracted: {extracted_data['extraction_time']}\n\n"
238
+
239
+ all_text += f"πŸ“Š CONTENT ANALYSIS:\n"
240
+ all_text += f"Content Blocks: {len(content_blocks)}\n"
241
+ all_text += f"Public Content: {sum(1 for b in content_blocks if b['is_public_content'])} blocks\n\n"
242
+
243
+ for i, block in enumerate(content_blocks[:10]):
244
+ all_text += f"--- BLOCK {i+1} ---\n"
245
+ all_text += f"Type: {block['content_type']}\n"
246
+ all_text += f"Words: {block['word_count']} | Public: {block['is_public_content']}\n"
247
+ all_text += f"Content: {block['content']}\n\n"
248
+
249
+ all_text += "="*50
250
 
251
+ # Split into chunks
252
+ splitter = CharacterTextSplitter(
253
+ separator="\n",
254
+ chunk_size=1000,
255
+ chunk_overlap=200,
256
+ length_function=len
257
+ )
258
+
259
+ chunks = splitter.split_text(all_text)
260
+ documents = [Document(page_content=chunk) for chunk in chunks]
261
+
262
+ # Create vector store
263
+ try:
264
+ embeddings = get_embeddings()
265
+ if embeddings is None:
266
+ return None, []
267
+ vectorstore = FAISS.from_documents(documents, embeddings)
268
+ return vectorstore, chunks
269
+ except Exception as e:
270
+ st.error(f"Vector store failed: {e}")
271
+ return None, []
272
+
273
+ def create_chatbot(vectorstore):
274
+ """Create conversational chatbot"""
275
+ try:
276
+ llm = get_llm()
277
+ if llm is None:
278
+ return None
279
+
280
+ memory = ConversationBufferMemory(
281
+ memory_key="chat_history",
282
+ return_messages=True,
283
+ output_key="answer"
284
+ )
285
+
286
+ chain = ConversationalRetrievalChain.from_llm(
287
+ llm=llm,
288
+ retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
289
+ memory=memory,
290
+ return_source_documents=True,
291
+ output_key="answer"
292
+ )
293
+ return chain
294
+ except Exception as e:
295
+ st.error(f"Chatbot creation failed: {str(e)}")
296
+ return None
297
+
298
+ def main():
299
+ st.title("πŸ“˜ Facebook Public Data Extractor")
300
+ st.markdown("Extract and analyze public Facebook data - Works on Hugging Face Spaces")
301
 
302
  if st.button("← Back to Main Dashboard"):
303
  st.switch_page("app.py")
304
 
305
+ # Initialize session state
306
+ if "extractor" not in st.session_state:
307
+ st.session_state.extractor = FacebookPublicExtractor()
308
+ if "facebook_data" not in st.session_state:
309
+ st.session_state.facebook_data = None
310
+ if "vectorstore" not in st.session_state:
311
+ st.session_state.vectorstore = None
312
+ if "chatbot" not in st.session_state:
313
+ st.session_state.chatbot = None
314
+ if "chat_history" not in st.session_state:
315
+ st.session_state.chat_history = []
316
 
317
+ # Sidebar
318
+ with st.sidebar:
319
+ st.header("βš™οΈ Facebook Configuration")
320
+
321
+ data_type = st.selectbox(
322
+ "Content Type",
323
+ ["page", "group", "event", "post", "marketplace"],
324
+ help="Select the type of Facebook content"
325
+ )
326
+
327
+ facebook_url = st.text_input(
328
+ "Facebook URL",
329
+ placeholder="https://www.facebook.com/Meta/",
330
+ help="Enter public Facebook URL (pages work best)"
331
+ )
332
+
333
+ # Suggested URLs that often work
334
+ st.markdown("### πŸš€ Test URLs")
335
+ test_urls = {
336
+ "Meta (Facebook)": "https://www.facebook.com/Meta/",
337
+ "Starbucks": "https://www.facebook.com/Starbucks/",
338
+ "NASA": "https://www.facebook.com/NASA/",
339
+ }
340
+
341
+ for name, url in test_urls.items():
342
+ if st.button(f"πŸ”— {name}", key=f"fb_{name}"):
343
+ st.session_state.current_fb_url = url
344
+ st.rerun()
345
+
346
+ if st.button("πŸš€ Extract Facebook Data", type="primary"):
347
+ url_to_use = facebook_url or getattr(st.session_state, 'current_fb_url', '')
348
+
349
+ if not url_to_use:
350
+ st.error("❌ Please enter a Facebook URL")
351
+ elif 'facebook.com' not in url_to_use:
352
+ st.error("❌ Please enter a valid Facebook URL")
353
+ else:
354
+ with st.spinner("πŸ”„ Extracting Facebook data..."):
355
+ extracted_data = st.session_state.extractor.extract_public_data(url_to_use, data_type)
356
+
357
+ if extracted_data.get("status") == "success":
358
+ st.session_state.facebook_data = extracted_data
359
+
360
+ # Process for AI
361
+ vectorstore, chunks = process_facebook_data(extracted_data)
362
+ if vectorstore:
363
+ st.session_state.vectorstore = vectorstore
364
+ st.session_state.chatbot = create_chatbot(vectorstore)
365
+ st.session_state.chat_history = []
366
+ st.success(f"βœ… Extracted {len(extracted_data['content_blocks'])} content blocks!")
367
+ else:
368
+ st.error("❌ Failed to process data for AI")
369
+ else:
370
+ error_msg = extracted_data.get("error", "Unknown error")
371
+ st.error(f"❌ Extraction failed: {error_msg}")
372
+
373
+ if st.session_state.facebook_data:
374
+ st.markdown("---")
375
+ if st.button("πŸ—‘οΈ Clear Data", type="secondary"):
376
+ st.session_state.facebook_data = None
377
+ st.session_state.vectorstore = None
378
+ st.session_state.chatbot = None
379
+ st.session_state.chat_history = []
380
+ st.rerun()
381
 
382
+ # Main content
383
+ col1, col2 = st.columns([1, 1])
 
 
 
 
384
 
385
+ with col1:
386
+ st.header("πŸ“Š Extraction Results")
387
+
388
+ if st.session_state.facebook_data:
389
+ data = st.session_state.facebook_data
390
+ page_info = data['page_info']
391
+ content_blocks = data['content_blocks']
392
+
393
+ st.success("βœ… Facebook Data Extracted")
394
+
395
+ # Metrics
396
+ col1, col2, col3 = st.columns(3)
397
+ with col1:
398
+ st.metric("Content Blocks", len(content_blocks))
399
+ with col2:
400
+ st.metric("Public Content", sum(1 for b in content_blocks if b['is_public_content']))
401
+ with col3:
402
+ st.metric("Response Code", page_info['response_code'])
403
+
404
+ # Page info
405
+ st.subheader("🏷️ Page Information")
406
+ st.write(f"**Title:** {page_info['title']}")
407
+ st.write(f"**URL Type:** {data['url_type']}")
408
+ st.write(f"**Access:** {page_info['access_note']}")
409
+ st.write(f"**Extracted:** {data['extraction_time'][:19]}")
410
+
411
+ # Content samples
412
+ st.subheader("πŸ“ Sample Content")
413
+ for i, block in enumerate(content_blocks[:3]):
414
+ with st.expander(f"Block {i+1} - {block['content_type']} ({block['word_count']} words)"):
415
+ st.write(block['content'])
416
+ st.caption(f"Public: {block['is_public_content']} | Links: {block['has_links']}")
417
+
418
+ else:
419
+ st.info("""
420
+ ## πŸ“˜ Facebook Public Data Extractor
421
+
422
+ **How it works:**
423
+ 1. Enter a public Facebook URL (pages work best)
424
+ 2. Click "Extract Facebook Data"
425
+ 3. View extracted public content
426
+ 4. Chat with AI about the data
427
+
428
+ **Supported URLs:**
429
+ - 🏒 Public Facebook Pages
430
+ - πŸ“˜ Public Groups (limited data)
431
+ - πŸŽ‰ Public Events
432
+ - πŸ“ Public Posts
433
+
434
+ **Limitations:**
435
+ - Only public content accessible
436
+ - No private group data
437
+ - Limited without login
438
+ """)
439
 
440
+ with col2:
441
+ st.header("πŸ’¬ AI Analysis Chat")
442
+
443
+ if st.session_state.chatbot and st.session_state.facebook_data:
444
+ # Display chat history
445
+ for chat in st.session_state.chat_history:
446
+ if chat["role"] == "user":
447
+ with st.chat_message("user"):
448
+ st.write(chat['content'])
449
+ elif chat["role"] == "assistant":
450
+ with st.chat_message("assistant"):
451
+ st.write(chat['content'])
452
+
453
+ # Chat input
454
+ user_input = st.chat_input("Ask about the Facebook data...")
455
+
456
+ if user_input:
457
+ st.session_state.chat_history.append({"role": "user", "content": user_input})
458
+
459
+ with st.spinner("πŸ€” AI is analyzing..."):
460
+ try:
461
+ response = st.session_state.chatbot.invoke({"question": user_input})
462
+ answer = response.get("answer", "I couldn't generate a response.")
463
+ st.session_state.chat_history.append({"role": "assistant", "content": answer})
464
+ st.rerun()
465
+ except Exception as e:
466
+ error_msg = f"AI Error: {str(e)}"
467
+ st.session_state.chat_history.append({"role": "assistant", "content": error_msg})
468
+ st.rerun()
469
+
470
+ # Suggested questions
471
+ if not st.session_state.chat_history:
472
+ st.subheader("πŸ’‘ Try asking:")
473
+ suggestions = [
474
+ "What is this Facebook page about?",
475
+ "Summarize the available public content",
476
+ "What type of content is most common?",
477
+ "Analyze the page's public information"
478
+ ]
479
+
480
+ for suggestion in suggestions:
481
+ if st.button(suggestion, key=f"fb_suggest_{suggestion}"):
482
+ st.info(f"Type: '{suggestion}' in chat")
483
+
484
+ elif st.session_state.facebook_data:
485
+ st.info("πŸ’¬ Start chatting with the AI about the Facebook data")
486
+ else:
487
+ st.info("πŸ” Extract Facebook data to enable AI chat")
488
 
489
  if __name__ == "__main__":
490
  main()