web-scraper-pro / app.py
ENLYAS's picture
Upload folder using huggingface_hub
0042832 verified
Raw History Blame Contribute Delete
6.55 kB
import gradio as gr
import requests
from bs4 import BeautifulSoup
import json
import re
from urllib.parse import urljoin, urlparse
import pandas as pd
from io import StringIO
class WebScraper:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
'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'
})
def scrape_page(self, url, scrape_type='all'):
try:
response = self.session.get(url, timeout=15)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
results = {'url': url, 'status': 'success', 'data': {}}
if scrape_type in ['all', 'text']:
text_content = soup.get_text(separator=' ', strip=True)
results['data']['text'] = text_content[:10000]
if scrape_type in ['all', 'links']:
links = []
for link in soup.find_all('a', href=True):
href = link['href']
full_url = urljoin(url, href)
links.append({'text': link.get_text(strip=True), 'url': full_url})
results['data']['links'] = links[:50]
if scrape_type in ['all', 'images']:
images = []
for img in soup.find_all('img'):
src = img.get('src') or img.get('data-src', '')
if src:
images.append({'src': urljoin(url, src), 'alt': img.get('alt', '')})
results['data']['images'] = images[:30]
if scrape_type in ['all', 'tables']:
tables = []
for table in soup.find_all('table'):
rows = []
for tr in table.find_all('tr'):
cells = [td.get_text(strip=True) for td in tr.find_all(['td', 'th'])]
if cells:
rows.append(cells)
if rows:
tables.append(rows)
results['data']['tables'] = tables[:5]
if scrape_type in ['all', 'headings']:
headings = {}
for level in range(1, 7):
tags = soup.find_all(f'h{level}')
headings[f'h{level}'] = [h.get_text(strip=True) for h in tags]
results['data']['headings'] = headings
if scrape_type in ['all', 'meta']:
meta = {}
for tag in soup.find_all('meta'):
name = tag.get('name') or tag.get('property', '')
content = tag.get('content', '')
if name and content:
meta[name] = content
results['data']['meta'] = meta
return json.dumps(results, indent=2, ensure_ascii=False)
except Exception as e:
return json.dumps({'url': url, 'status': 'error', 'error': str(e)}, indent=2)
def scrape_multiple(self, urls_text, scrape_type='all'):
urls = [u.strip() for u in urls_text.split('\n') if u.strip()]
results = []
for url in urls[:10]:
result = self.scrape_page(url, scrape_type)
results.append(result)
return '\n\n---\n\n'.join(results)
def export_to_csv(self, url, scrape_type='tables'):
try:
response = self.session.get(url, timeout=15)
soup = BeautifulSoup(response.text, 'html.parser')
tables = soup.find_all('table')
if not tables:
return 'No tables found on this page.'
csv_output = []
for i, table in enumerate(tables[:3]):
csv_output.append(f'### Table {i+1}\n')
df = pd.read_html(StringIO(str(table)))[0]
csv_output.append(df.to_csv(index=False))
return '\n'.join(csv_output)
except Exception as e:
return f'Error: {str(e)}'
def scrape_website(url, scrape_type, multiple_urls):
scraper = WebScraper()
if multiple_urls:
return scraper.scrape_multiple(url, scrape_type)
return scraper.scrape_page(url, scrape_type)
def export_data(url, scrape_type):
scraper = WebScraper()
return scraper.export_to_csv(url, scrape_type)
with gr.Blocks(theme=gr.themes.Soft(), title='Web Scraper Pro') as demo:
gr.Markdown('# 🕷️ Web Scraper Pro\n\nExtract data from any website with ease. Supports text, links, images, tables, and more.')
with gr.Row():
with gr.Column(scale=2):
url_input = gr.Textbox(
label='Website URL(s)',
placeholder='https://example.com\n\nFor multiple URLs, enter one per line',
lines=3
)
with gr.Row():
scrape_type = gr.Dropdown(
choices=['all', 'text', 'links', 'images', 'tables', 'headings', 'meta'],
value='all',
label='Scrape Type'
)
multiple_urls = gr.Checkbox(label='Multiple URLs Mode', value=False)
scrape_btn = gr.Button('🚀 Start Scraping', variant='primary', size='lg')
export_btn = gr.Button('📥 Export Tables to CSV', variant='secondary')
with gr.Column(scale=3):
output = gr.Textbox(
label='Scraped Results',
lines=20,
max_lines=50
)
gr.Markdown('### 📊 Quick Stats')
with gr.Row():
stat_text = gr.Number(label='Characters Extracted', value=0)
stat_links = gr.Number(label='Links Found', value=0)
stat_images = gr.Number(label='Images Found', value=0)
gr.Markdown('### 💡 Tips\n- Use **Multiple URLs Mode** to scrape several pages at once\n- Select specific **Scrape Type** for faster results\n- **Export Tables** downloads structured data as CSV')
scrape_btn.click(
fn=scrape_website,
inputs=[url_input, scrape_type, multiple_urls],
outputs=output
)
export_btn.click(
fn=export_data,
inputs=[url_input, scrape_type],
outputs=output
)
if __name__ == '__main__':
demo.launch(server_name='0.0.0.0', server_port=7860, share=True)