Links-Scrape / app.py
isan2001's picture
Update app.py
cc43788 verified
Raw
History Blame Contribute Delete
7.16 kB
import os
import sys
# --- OTOMATISASI INSTALASI PLAYWRIGHT & DEPENDENSI LINUX ---
# Langkah ini mendeteksi jika aplikasi berjalan di server Hugging Face (Linux)
if not os.path.exists("/home/user/.cache/ms-playwright"):
print("Menginstal Chromium dan dependensi sistem Linux yang dibutuhkan...")
# Menginstal biner chromium
os.system("python -m playwright install chromium")
# Menginstal pustaka sistem (APT) yang kurang agar Chromium bisa jalan di Ubuntu HF
os.system("python -m playwright install-deps chromium")
import random
import time
import urllib.parse
from datetime import datetime
import re
import gradio as gr
from playwright.sync_api import sync_playwright
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
]
def process_target(browser, target, rentang_waktu, max_halaman, progress=gr.Progress()):
query_lengkap = f"{target} site:instagram.com"
clean_query = urllib.parse.quote_plus(query_lengkap)
context_args = {
"user_agent": random.choice(user_agents),
"viewport": {"width": 1366, "height": 768},
"locale": "id-ID",
"timezone_id": "Asia/Jakarta"
}
context = browser.new_context(**context_args)
page = context.new_page()
page.add_init_script("delete navigator.__proto__.webdriver;")
clean_links = set()
log_output = f"Memulai pencarian untuk target: '{target}'\n"
try:
for page_num in range(1, int(max_halaman) + 1):
progress(page_num / int(max_halaman), desc=f"Memproses Halaman {page_num}")
start_index = (page_num - 1) * 10
tbs_param = f"&tbs={rentang_waktu}" if rentang_waktu != "all" else ""
google_url = f"https://www.google.com/search?q={clean_query}{tbs_param}&start={start_index}"
log_output += f"[SEARCHING] Halaman {page_num} -> URL: {google_url}\n"
page.goto(google_url, wait_until="domcontentloaded", timeout=30000)
time.sleep(random.uniform(2, 4))
if page_num == 1:
tombol_persetujuan = ["button:has-text('Setuju')", "button:has-text('Accept all')", "#L2AGLb"]
for selector in tombol_persetujuan:
if page.is_visible(selector):
page.click(selector)
time.sleep(2)
break
is_captcha = page.is_visible("form#captcha-form") or page.is_visible("#captcha") or "detected unusual traffic" in page.content().lower()
if is_captcha:
log_output += "[PENTING] Google mendeteksi CAPTCHA! Karena berjalan secara headless di server cloud, proses dihentikan untuk keamanan.\n"
break
if "tidak cocok dengan dokumen apa pun" in page.content().lower() or "did not match any documents" in page.content().lower():
log_output += f"[INFO] Hasil pencarian sudah habis di halaman {page_num}.\n"
break
html_content = page.content()
raw_links = re.findall(r'https?://(?:www\.)?instagram\.com/[a-zA-Z0-9_\-\./\?&=]+', html_content)
links_in_this_page = 0
for link in raw_links:
link = link.split('"')[0].split("'")[0].split(')')[0].split('\\')[0]
if "google.com" in link:
continue
is_postingan = any(pola in link for pola in ["/p/", "/reel/", "/tv/"])
if not is_postingan:
continue
if link not in clean_links:
clean_links.add(link)
links_in_this_page += 1
log_output += f"[PAGE {page_num}] Menemukan {links_in_this_page} link postingan baru.\n"
time.sleep(random.randint(2, 5))
log_output += f"\n[SELESAI] Total menemukan {len(clean_links)} link unik untuk target '{target}'\n"
except Exception as e:
log_output += f"[ERROR]: {e}\n"
finally:
page.close()
context.close()
return clean_links, log_output
def scraper_interface(target, rentang_waktu, max_halaman, progress=gr.Progress()):
if not target:
return "Target query tidak boleh kosong.", None, None
file_name = "instagram_links_output.txt"
if os.path.exists(file_name):
os.remove(file_name)
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
args=[
"--disable-blink-features=AutomationControlled",
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-infobars",
"--ignore-certificate-errors"
]
)
links, logs = process_target(browser, target, rentang_waktu, max_halaman, progress)
browser.close()
if links:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(file_name, "w", encoding="utf-8") as f:
for link in links:
f.write(f"[{timestamp}] [Target: {target}] {link}\n")
links_text = "\n".join(links)
return logs, links_text, file_name
else:
return logs, "Tidak ada link yang ditemukan.", None
# ===================== UI DESIGN (GRADIO) =====================
with gr.Blocks(title="Google Instagram Scraper") as demo:
gr.Markdown("# 🕷️ Google Instagram Link Scraper")
gr.Markdown("Cari tautan postingan Instagram melalui Google Search berdasarkan target kata kunci, rentang waktu, dan jumlah halaman.")
with gr.Row():
with gr.Column(scale=1):
input_target = gr.Textbox(label="Target / Kata Kunci", placeholder="Contoh: Pengembang Aplikasi", value="Pengembang Aplikasi")
input_waktu = gr.Dropdown(
label="Rentang Waktu Pencarian",
choices=[("24 Jam Terakhir", "qdr:d"), ("1 Minggu Terakhir", "qdr:w"), ("1 Bulan Terakhir", "qdr:m"), ("Semua Waktu", "all")],
value="qdr:d"
)
input_halaman = gr.Slider(label="Maksimal Halaman Pencarian", minimum=1, maximum=35, step=1, value=5)
btn_run = gr.Button("Mulai Scraping", variant="primary")
with gr.Column(scale=2):
output_logs = gr.TextArea(label="Proses Log / Status", interactive=False, lines=6)
output_file = gr.File(label="Unduh Hasil (.txt)")
output_links = gr.TextArea(label="Hasil Tautan Instagram", interactive=False, lines=10)
btn_run.click(
fn=scraper_interface,
inputs=[input_target, input_waktu, input_halaman],
outputs=[output_logs, output_links, output_file]
)
if __name__ == "__main__":
demo.launch()