Penulis
Aditya Sundar - Universiti Waseda
Abstrak
Projek ini membangunkan web crawler yang direka untuk meneroka laman web secara sistematik dan menjana senarai URL yang komprehensif, tanpa mengira ketersediaan sitemap. Crawler mengendalikan kedua-dua kandungan statik dan dinamik, menjejaki rujukan luaran, dan beroperasi dengan cekap pada perkakasan yang terhad.
Keupayaan Utama:
- Crawling tak segerak dengan keserentakan boleh dikonfigurasi
- Penemuan URL berasaskan BFS untuk liputan sistematik
- Penjejakan dan analisis rujukan luaran
- Sokongan kandungan dinamik melalui Playwright
- Penyimpanan berterusan berasaskan SQLite
1. Pengenalan
Web crawling membolehkan sistem automatik melayari laman web dan mengumpul data. Walaupun sitemap menyediakan senarai URL berstruktur, tidak semua laman web mempunyainya. Crawler ini:
- Berfungsi pada tapak dengan atau tanpa sitemap
- Menjana sitemap luaran (URL yang merujuk domain lain)
- Berjalan pada perkakasan spek rendah tanpa proksi
- Mengendalikan laman web berskala besar dengan cekap
2. Metodologi
2.1 Tindanan Teknologi
| Teknologi | Tujuan |
|---|
| Python | Bahasa utama |
| aiohttp | Permintaan HTTP tak segerak |
| BeautifulSoup | Penghuraian HTML dan pengekstrakan pautan |
| asyncio | Pelaksanaan kod serentak |
| SQLite | Penyimpanan URL berterusan |
| Playwright | Rendering kandungan dinamik |
| fake_useragent | Mengelakkan pengesanan bot |
2.2 Aliran Kerja Crawler
- Permulaan: Normalisasi URL permulaan, semak robots.txt, cipta jadual pangkalan data
- Pengambilan URL: Permintaan batch tak segerak dengan kelewatan
- Pengekstrakan Pautan: Huraikan tag anchor, normalisasikan URL
- Penyimpanan Data: SQLite untuk URL, ralat, domain luaran
- Keserentakan: Had boleh dikonfigurasi (lalai: 100 serentak)
- Penyelesaian: Berhenti apabila tiada URL baharu atau had dicapai
2.3 Pematuhan Robots.txt
def check_robots_txt(url, timeout=5, retry_count=3):
robots_url = f"{parsed_url.scheme}://{parsed_url.netloc}/robots.txt"
rp.set_url(robots_url)
for attempt in range(retry_count):
try:
response = requests.get(robots_url, timeout=timeout)
if response.status_code < 400:
rp.parse(response.text.splitlines())
return
except requests.Timeout:
print(f"Timeout, mencuba semula...")
# Lalai kepada membenarkan crawl jika robots.txt tidak tersedia
rp.parse(['User-agent: *', 'Disallow:'])
2.4 Algoritma BFS
Crawler menggunakan Breadth-First Search untuk meneroka URL:
- Memproses semua URL pada kedalaman semasa sebelum bergerak lebih dalam
- Memastikan liputan sistematik peringkat demi peringkat
- Membenarkan penyambungan semula jika terganggu
2.5 Pengendalian Ralat
| Jenis Ralat | Tindakan |
|---|
| 404, 403, 400 | Langkau (tiada cuba semula) |
| 429 | Tunggu untuk header Retry-After |
| 500, 502, 503 | Cuba semula dengan kelewatan |
| Timeout | Cuba semula sehingga 3 kali |
3. Keputusan
3.1 Statistik Crawling
| Jenis Laman Web | URL Dalaman | Rujukan Luaran |
|---|
| Tapak Hiburan 1 | 47,870 | 7,010,999 |
| Tapak Permainan 2 | 143,058 | 3,027,460 |
| Tapak Siaran Akhbar | 99,243 | 2,136,887 |
| Tapak Berita 6 | 117,164 | 1,895,515 |
| Tapak Kerajaan 1 | 28,841 | 55,700 |
| Tapak Pendidikan 1 | 50,458 | 28,328 |
Jumlah:
- URL Dalaman: 1,121,407
- Rujukan Luaran: 18,957,040
Nisbah URL Luaran kepada Dalaman mengikut Jenis Laman Web
Tapak hiburan/berita mempunyai nisbah rujukan luaran yang lebih tinggi daripada tapak kerajaan, mencerminkan strategi kandungan yang berbeza.
3.2 Analisis Ralat
| Jenis Ralat | Bilangan |
|---|
| Status 404 | 43,611 |
| Status 503 | 29,555 |
| Ralat penyahkodan | 3,271 |
| Sekatan Robots.txt | 2,696 |
| Ralat lain | 124,261 |
| Cuba semula maksimum dicapai | 11,994 |
Pautan sebenarnya dilangkau: 62,050
3.3 Pandangan SEO
- Tapak media: Nisbah rujukan luaran yang tinggi mungkin meningkatkan kredibiliti
- Tapak kerajaan: Tumpuan pada pautan dalaman adalah sesuai
- Pendekatan seimbang disyorkan untuk kebanyakan tapak
4. Pengoptimuman
Pengehadan Kadar
connector = aiohttp.TCPConnector(limit=100) # Boleh diselaraskan
Had yang lebih rendah mencegah ralat 429 tetapi memperlahankan crawling.
Kandungan Dinamik (SPA)
Playwright mengendalikan kandungan yang dirender JavaScript:
async def scrape_all_links(start_url):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
Normalisasi URL
- Buang fragmen
- Menyatukan skema (HTTPS sahaja)
- Buang garis miring trailing
- Pangkalan data mencegah crawling duplikat
5. Hala Tuju Masa Depan
- Sokongan proksi: Mengurangkan risiko sekatan IP
- Perkakasan lebih baik: Mengendalikan crawl yang lebih besar
- Integrasi Scrapy: Memanfaatkan ciri rangka kerja yang teguh
- Analisis graf: Memetakan hubungan laman web menggunakan embeddings
Rujukan
- aiohttp - Klien/pelayan HTTP tak segerak untuk Python
- BeautifulSoup - Pustaka penghuraian HTML/XML
- Playwright - Rangka kerja automasi pelayar
- SQLite - Enjin pangkalan data ringan