Scraping Banyak URL dari urls.txt dengan Python

Scraping Banyak URL dari urls.txt dengan Python

Cara simpel baca daftar URL dari urls.txt lalu scraping satu per satu pakai Python, lengkap dengan timeout, progres, dan simpan hasil ke CSV.

Intinya gini

Kalau lu lagi scraping banyak halaman, jangan hardcode daftar URL di script. Lebih enak simpan aja di file urls.txt, satu URL per baris. Jadi kalau mau nambah atau ngurangin target, tinggal edit file teksnya, bukan bongkar script lagi.

Model begini cocok banget buat kerjaan yang isinya puluhan sampai ratusan URL. Lebih rapi, lebih gampang di-maintain, dan kalau ada URL yang bermasalah, prosesnya masih bisa lanjut ke URL berikutnya.

Siapkan file urls.txt

Bikin file bernama urls.txt di folder yang sama dengan script Python. Isi formatnya simpel:

https://domain-anda.com/series-satu
https://domain-anda.com/series-dua
https://domain-anda.com/series-tiga
https://domain-anda.com/series-empat

Pastikan satu URL per baris. Jangan dicampur koma atau spasi aneh-aneh, biar gampang dibaca script.

Script Python untuk baca urls.txt

Di bawah ini versi yang gue pakai buat baca file teks, scraping per URL, lalu simpan hasilnya ke CSV.

import requests
import json
from lxml import html
import pandas as pd

# 1. Membaca daftar URL dari file urls.txt
txt_filename = "urls.txt"

try:
    with open(txt_filename, "r", encoding="utf-8") as file:
        # Membaca baris per baris, dan menghapus spasi/enter tambahan (strip)
        urls = [line.strip() for line in file if line.strip()]
    print(f"Total {len(urls)} URL berhasil dimuat dari '{txt_filename}'.\n")
except FileNotFoundError:
    print(f"[ERROR] File '{txt_filename}' tidak ditemukan. Buat filenya terlebih dahulu!")
    exit()

headers = {
    "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"
}

xpath_expr = '//script[@type="application/ld+json"]/text()'
results = []

# 2. Loop proses scraping
for index, url in enumerate(urls, start=1):
    print(f"[{index}/{len(urls)}] Memproses: {url}...")
    
    try:
        response = requests.get(url, headers=headers, timeout=10) # Tambah timeout 10 detik
        
        if response.status_code == 200:
            tree = html.fromstring(response.content)
            script_contents = tree.xpath(xpath_expr)
            
            found = False
            
            for raw_json in script_contents:
                try:
                    data = json.loads(raw_json.strip())
                    
                    if isinstance(data, dict) and data.get("@type") == "VideoObject":
                        
                        thumbnail_url = data.get("thumbnailUrl")
                        if isinstance(thumbnail_url, list) and len(thumbnail_url) > 0:
                            thumbnail_url = thumbnail_url[0]

                        item_data = {
                            "url": url,
                            "name": data.get("name"),
                            "description": data.get("description"),
                            "thumbnailUrl": thumbnail_url,
                            "uploadDate": data.get("uploadDate"),
                            "embedUrl": data.get("embedUrl")
                        }
                        
                        results.append(item_data)
                        found = True
                        break
                        
                except json.JSONDecodeError:
                    continue
            
            if not found:
                print(f"  └─ [WARNING] VideoObject tidak ditemukan")
                
        else:
            print(f"  └─ [ERROR] Gagal akses, Status: {response.status_code}")
            
    except Exception as e:
        print(f"  └─ [ERROR] Masalah pada URL ini: {e}")

# 3. Simpan Hasil ke File CSV
if results:
    df = pd.DataFrame(results)
    csv_filename = "hasil_scrape_series.csv"
    df.to_csv(csv_filename, index=False, encoding='utf-8-sig')
    print(f"\nSelesai! {len(results)} dari {len(urls)} URL berhasil disimpan ke '{csv_filename}'.")
else:
    print("\nTidak ada data yang berhasil diekstrak.")

Kenapa cara ini enak

  • Gampang nambah URL — tinggal edit urls.txt.
  • Ada progres — format [1/100] bikin lu tahu prosesnya lagi di mana.
  • Ada timeout — kalau satu URL ngadat, script nggak nunggu selamanya.
  • Baris kosong aman — line.strip() buang spasi dan enter kosong.

Masalah yang sering kejadian

1. File urls.txt nggak ketemu
Kalau muncul error file tidak ditemukan, biasanya file-nya belum ada atau path-nya beda folder sama script.

[ERROR] File 'urls.txt' tidak ditemukan. Buat filenya terlebih dahulu!

Solusi: pastikan urls.txt ada di folder yang sama dengan script Python.

2. Ada URL yang lemot atau down
Kalau tanpa timeout, script bisa terasa hang. Makanya timeout=10 penting biar proses lanjut terus.

3. Data nggak ketemu
Kadang halaman memang nggak punya VideoObject di JSON-LD, jadi hasilnya kosong walau URL sukses dibuka.

Solusi: cek struktur HTML targetnya. Mungkin perlu XPath lain, atau jenis data yang dicari bukan VideoObject.

Catatan kecil biar lebih aman

Kalau target lu banyak banget, sebaiknya tambahin jeda antar request biar nggak terlalu agresif. Bisa juga pakai retry kalau situsnya suka flaky. Intinya, jangan cuma fokus ke hasil, tapi juga ke stabilitas prosesnya.

Kalau nanti mau dikembangin lagi, script ini gampang banget diubah buat ambil tipe data lain selain video. Tinggal ganti bagian pengecekan @type dan field yang mau disimpan.

Tags: Catatan Teknis, Python, Scraping, CSV, requests, lxml