Krixter commited on
Commit
58f1338
Β·
verified Β·
1 Parent(s): 45cb56f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -12
app.py CHANGED
@@ -2,7 +2,6 @@ import gradio as gr
2
  import requests
3
  from bs4 import BeautifulSoup
4
  import time
5
- import os
6
  import zipfile
7
  from urllib.parse import urlparse
8
  import re
@@ -59,24 +58,56 @@ def scrape_kemono(links_text, delay_sec, max_retries):
59
  # Parse HTML for Text and Title extraction
60
  soup = BeautifulSoup(html_content, 'html.parser')
61
 
62
- # Extract Title (Kemono specifically uses h1 with class 'post__title')
 
 
 
 
 
 
63
  title_tag = soup.find('h1', class_='post__title')
64
- title = title_tag.get_text(strip=True) if title_tag else f"Untitled_Post_{i+1}"
 
 
 
 
 
65
 
66
- # Extract Content Text (Kemono uses 'post__content' or 'post__body')
67
- content_tag = soup.find('div', class_='post__content')
68
- if not content_tag:
69
- content_tag = soup.find('div', class_='post__body')
70
 
71
- text_content = content_tag.get_text(separator='\n', strip=True) if content_tag else "[No text content found in this post.]"
 
 
 
 
 
 
 
72
 
73
- # Append formatted data to our combined text string
 
 
 
 
 
 
 
74
  post_text = f"========================================================================\n"
75
  post_text += f"TITLE: {title}\n"
76
  post_text += f"URL: {link}\n"
77
  post_text += f"========================================================================\n\n"
78
- post_text += f"{text_content}\n\n\n"
79
 
 
 
 
 
 
 
 
 
 
80
  extracted_data.append(post_text)
81
 
82
  except Exception as e:
@@ -91,7 +122,7 @@ def scrape_kemono(links_text, delay_sec, max_retries):
91
  # --- Gradio UI Layout ---
92
  with gr.Blocks(theme=gr.themes.Soft()) as app:
93
  gr.Markdown("# 🦊 Kemono.cr Batch Scraper & Extractor")
94
- gr.Markdown("Paste a list of links (or raw HTML tags from your `links.txt` file). The scraper will fetch each link, extract the title and text, save the raw HTMLs in a ZIP, and give you a combined TXT document.")
95
 
96
  with gr.Row():
97
  with gr.Column(scale=2):
@@ -102,7 +133,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
102
  )
103
 
104
  with gr.Row():
105
- delay_input = gr.Slider(minimum=0, maximum=15, value=2, step=0.5, label="Delay Between Requests (Seconds)")
106
  retry_input = gr.Slider(minimum=1, maximum=5, value=3, step=1, label="Max Retries per Link")
107
 
108
  start_btn = gr.Button("πŸš€ Start Extraction", variant="primary")
 
2
  import requests
3
  from bs4 import BeautifulSoup
4
  import time
 
5
  import zipfile
6
  from urllib.parse import urlparse
7
  import re
 
58
  # Parse HTML for Text and Title extraction
59
  soup = BeautifulSoup(html_content, 'html.parser')
60
 
61
+ # Check for Cloudflare block
62
+ page_title = soup.find('title')
63
+ if page_title and "Just a moment" in page_title.get_text():
64
+ extracted_data.append(f"--- BLOCKED BY CLOUDFLARE: {link} (Increase your delay!) ---\n")
65
+ continue
66
+
67
+ # 1. EXTRACT TITLE (Better Fallbacks)
68
  title_tag = soup.find('h1', class_='post__title')
69
+ if title_tag:
70
+ title = title_tag.get_text(strip=True)
71
+ elif page_title:
72
+ title = page_title.get_text(strip=True).replace(" | Kemono", "")
73
+ else:
74
+ title = f"Untitled_Post_{i+1}"
75
 
76
+ # 2. EXTRACT TEXT CONTENT
77
+ content_tag = soup.find('div', class_='post__content') or soup.find('div', class_='post__body')
78
+ text_content = content_tag.get_text(separator='\n', strip=True) if content_tag else ""
 
79
 
80
+ # 3. EXTRACT ATTACHMENTS & IMAGES
81
+ media_links = []
82
+ # Look for attachments
83
+ attachments = soup.find_all('a', class_='post__attachment-link')
84
+ for atk in attachments:
85
+ href = atk.get('href')
86
+ if href:
87
+ media_links.append("Attachment: " + (href if href.startswith('http') else f"https://kemono.cr{href}"))
88
 
89
+ # Look for images inside the post
90
+ images = soup.find_all('img', class_='post__image')
91
+ for img in images:
92
+ src = img.get('src')
93
+ if src:
94
+ media_links.append("Image: " + (src if src.startswith('http') else f"https://kemono.cr{src}"))
95
+
96
+ # Build the final text block
97
  post_text = f"========================================================================\n"
98
  post_text += f"TITLE: {title}\n"
99
  post_text += f"URL: {link}\n"
100
  post_text += f"========================================================================\n\n"
 
101
 
102
+ if not text_content and not media_links:
103
+ post_text += "[No text or media content found. The post might be empty or locked.]\n\n"
104
+ else:
105
+ if text_content:
106
+ post_text += f"--- TEXT ---\n{text_content}\n\n"
107
+ if media_links:
108
+ post_text += f"--- MEDIA LINKS ---\n" + "\n".join(media_links) + "\n\n"
109
+
110
+ post_text += "\n"
111
  extracted_data.append(post_text)
112
 
113
  except Exception as e:
 
122
  # --- Gradio UI Layout ---
123
  with gr.Blocks(theme=gr.themes.Soft()) as app:
124
  gr.Markdown("# 🦊 Kemono.cr Batch Scraper & Extractor")
125
+ gr.Markdown("Paste a list of links (or raw HTML tags from your `links.txt` file). The scraper will fetch each link, extract the title, text, and media links, save the raw HTMLs in a ZIP, and give you a combined TXT document.")
126
 
127
  with gr.Row():
128
  with gr.Column(scale=2):
 
133
  )
134
 
135
  with gr.Row():
136
+ delay_input = gr.Slider(minimum=0, maximum=15, value=2.5, step=0.5, label="Delay Between Requests (Seconds)")
137
  retry_input = gr.Slider(minimum=1, maximum=5, value=3, step=1, label="Max Retries per Link")
138
 
139
  start_btn = gr.Button("πŸš€ Start Extraction", variant="primary")