Screaming Frog adalah crawler pilihan untuk kebanyakan SEO, tetapi anda mungkin sudah terlanggar dindingnya: had 500-URL pada versi percuma, RAM memuncak pada laman besar, atau ingin mengautomasi crawl tanpa mengawasi GUI. Scrapy adalah rangka kerja Python sumber terbuka yang menghapuskan had tersebut.

Jika anda boleh menjalankan npm install atau git clone, anda boleh menjalankan Scrapy. Keluk pembelajaran adalah nyata tetapi boleh diurus, terutamanya jika anda sudah selesa dengan alat CLI melalui aliran kerja pengaturcaraan agentik.

Mengapa Scrapy?

Faedah Utama

Screaming Frog berfungsi dengan baik untuk audit pantas. Tetapi ia mempunyai had:

Had Kesan
Had percuma 500 URL Memerlukan lesen $259/tahun untuk laman lebih besar
Rakus memori Crawl besar boleh menggunakan 8GB+ RAM
Bergantung pada GUI Sukar untuk automasi atau jadual
Penyesuaian terhad Pilihan konfigurasi adalah tetap

Scrapy menyelesaikan ini:

Scrapy Apa yang anda dapat
Percuma dan sumber terbuka Tiada had URL, tiada yuran lesen
Jejak memori lebih rendah Baris gilir disokong cakera memastikan RAM terkawal
CLI-asli Boleh skrip, boleh cron, sedia CI/CD
Penyesuaian Python penuh Ekstrak apa yang anda perlukan, tapis cara yang anda mahu
Jeda/Sambung Henti dan teruskan crawl besar bila-bila masa
Scrapy tidak akan menggantikan Screaming Frog untuk semua. Audit pantas masih lebih cepat dalam GUI. Tetapi untuk crawl berskala besar, automasi, dan pengekstrakan tersuai, ia berbaloi untuk ada dalam toolkit anda.

Pemasangan

Persediaan

Scrapy berjalan pada Python. Gunakan persekitaran maya untuk memastikan semuanya bersih:

Debian/Ubuntu:

sudo apt install python3.11-venv
python3 -m venv venv
source venv/bin/activate
pip install scrapy

macOS:

python3 -m venv venv
source venv/bin/activate
pip install scrapy

Windows:

python -m venv venv
venv\Scripts\activate
pip install scrapy
Persekitaran Maya Penting
Sentiasa gunakan venv. Pemasangan global menyebabkan konflik kebergantungan dan merosakkan kebolehulangan.

Mencipta Projek

Dengan Scrapy dipasang:

scrapy startproject myproject
cd myproject
scrapy genspider sitename example.com

Ini mencipta:

myproject/
    scrapy.cfg
    myproject/
        __init__.py
        items.py
        middlewares.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            sitename.py

Kod spider masuk dalam spiders/sitename.py. Konfigurasi dalam settings.py.

Tetapan untuk Crawling Sopan

Kritikal

Konfigurasikan settings.py sebelum menjalankan apa-apa. Disekat membazir lebih banyak masa daripada crawling perlahan.

# Crawling sopan
CONCURRENT_REQUESTS_PER_DOMAIN = 5
DOWNLOAD_DELAY = 1
ROBOTSTXT_OBEY = True

# AutoThrottle - menyesuaikan kelajuan berdasarkan respons pelayan
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 5
AUTOTHROTTLE_MAX_DELAY = 60
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
AUTOTHROTTLE_DEBUG = True

# Had keselamatan
CLOSESPIDER_PAGECOUNT = 10000

# Output
FEED_EXPORT_ENCODING = "utf-8"
Dengan AutoThrottle diaktifkan, 5 permintaan serentak adalah titik permulaan yang munasabah. AutoThrottle akan berundur secara automatik jika pelayan bergelut. Tanpa AutoThrottle, mulakan lebih rendah pada 1-3.

AutoThrottle

AutoThrottle memantau masa respons pelayan dan menyesuaikan kelajuan crawl secara automatik:

  • Respons pantas → mempercepatkan
  • Respons perlahan → memperlahankan
  • Ralat/timeout → memperlahankan dengan ketara

Tidak seperti kelewatan tetap Screaming Frog, ia menyesuaikan diri dengan keadaan pelayan sebenar.

Pengendalian Kod Status

Secara lalai, HttpErrorMiddleware Scrapy menggugurkan respons bukan 2xx secara senyap. Ini bermakna 404, 301, 500 dibuang sebelum sampai ke callback anda. Crawl anda mungkin menunjukkan 100% kod status 200, bukan kerana laman sempurna, tetapi kerana ralat sedang ditapis.

Tambah ini ke kelas spider anda untuk menangkap semua kod status:

handle_httpstatus_list = [200, 301, 302, 403, 404, 500, 502, 503]

Screaming Frog menangkap semua kod status secara lalai. Tetapan ini menjadikan Scrapy selaras dengan tingkah laku tersebut.

Prestasi Dunia Sebenar

Penanda Aras

Nombor sebenar dari crawl ujian dengan 5 permintaan serentak dan AutoThrottle diaktifkan:

Kemajuan Crawl Halaman/Minit Nota
0-200 halaman 14-22 Peningkatan
200-500 halaman 10-12 Menstabilkan
500-1,000 halaman 7-10 AutoThrottle menyesuaikan
1,000+ halaman 5-7 Keadaan stabil
Kelajuan vs. Kebolehpercayaan
Kelajuan ini kelihatan perlahan. Itulah maksudnya. AutoThrottle mengutamakan kesihatan pelayan berbanding kelajuan mentah. Disekat dan bermula semula membazir lebih banyak masa daripada crawl yang berkaedah.

Perbandingan Ciri

Ciri Screaming Frog Scrapy
Kos Percuma <500 URL, ~$259/tahun Percuma, sumber terbuka
Saiz crawl maks Terhad memori Baris gilir disokong cakera
Penyesuaian Pilihan config terhad Kod Python penuh
Penjadualan Manual atau pihak ketiga CLI asli, boleh cron
Jeda/Sambung Ya Ya (dengan JOBDIR)
Keluk pembelajaran Rendah (GUI) Sederhana (kod)
Had kadar Kelewatan tetap asas AutoThrottle (adaptif)
Rendering JavaScript Pilihan (Chrome) Pilihan (playwright/splash)
Kod status Semua secara lalai Memerlukan konfigurasi
Penapisan subdomain Kotak pilihan GUI Kod (regex fleksibel)
Format eksport CSV, Excel, dll. JSON, CSV, XML, tersuai
Integrasi CI/CD Sukar Asli

Penapisan URL

Kawalan Tepat

Screaming Frog menggunakan kotak pilihan. Scrapy menggunakan kod. Pertukaran adalah keluk pembelajaran untuk ketepatan.

Mengecualikan laluan antarabangsa:

import re
from urllib.parse import urlparse

class MySiteSpider(scrapy.Spider):
    name = "mysite"
    allowed_domains = ["example.com", "www.example.com"]
    start_urls = ["https://www.example.com/"]

    # Langkau laluan antarabangsa seperti /uk/, /fr/, /de/
    EXCLUDED_PATTERNS = re.compile(
        r"/(in|au|th|es|hk|sg|ph|my|ca|cn|uk|kr|id|fr|vn|de|jp|nl|it|tw)/"
    )

    def filter_links(self, links):
        filtered = []
        for link in links:
            hostname = urlparse(link.url).hostname or ""
            if hostname not in ("example.com", "www.example.com"):
                continue
            if self.EXCLUDED_PATTERNS.search(link.url):
                continue
            filtered.append(link)
        return filtered

Anda boleh menapis mengikut corak URL, parameter pertanyaan, pengepala respons, kandungan halaman, atau sebarang kombinasi.

Jeda dan Sambung

Penting

Untuk crawl melebihi 1,000 halaman, aktifkan jeda/sambung dengan JOBDIR:

scrapy crawl myspider -o output.json -s JOBDIR=crawl_state

Scrapy menyimpan keadaan ke crawl_state/. Tekan Ctrl+C untuk jeda. Jalankan arahan yang sama untuk menyambung.

Sentiasa gunakan JOBDIR untuk crawl pengeluaran. Melindungi daripada isu rangkaian, permulaan semula sistem, atau hanya perlu berhenti untuk hari itu.

Keadaan termasuk URL yang tertunda, URL yang dilihat, dan baris gilir permintaan. Ini lebih mantap daripada ciri simpan/muat Screaming Frog kerana ia berasaskan fail dan bertahan selepas permulaan semula sistem.

Rendering JavaScript

Scrapy mengambil HTML mentah sahaja. Ia tidak merender JavaScript. Ini sama seperti apa yang dikembalikan oleh curl.

Untuk kebanyakan crawl SEO, ini tidak menjadi masalah:

  • Tag meta, canonical, dan h1 biasanya dalam HTML awal
  • Enjin carian terutamanya mengindeks kandungan yang dirender pelayan
  • Kebanyakan laman e-dagang dan kandungan dirender pelayan

Jika laman sasaran anda merender kandungan di sisi klien, anda mempunyai pilihan:

Pakej Nota
scrapy-playwright Menggunakan Chromium/Firefox/WebKit. Disyorkan untuk laman JS moden
scrapy-splash Ringan, renderer berasaskan Docker
scrapy-selenium Pendekatan lama, masih berfungsi

Rendering JS jauh lebih perlahan dan intensif sumber. Hanya tambah jika laman memerlukannya.

Screaming Frog mempunyai pertukaran yang sama. Mengaktifkan rendering JavaScript menggunakan Chrome di sebalik tabir dan melambatkan crawl dengan ketara.

Pengurusan Memori

Pada ~1,300 halaman dengan pengekstrakan medan penuh:

  • Memori: ~265 MB
  • CPU: ~4%

Menggunakan JOBDIR memindahkan baris gilir permintaan ke cakera, memastikan memori rendah. Untuk crawl yang sangat besar (100k+ URL), tambah tetapan ini:

MEMUSAGE_LIMIT_MB = 1024
MEMUSAGE_WARNING_MB = 800
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue'

Ini mengehadkan penggunaan memori dan memaksa baris gilir disokong cakera untuk penjadual.

Data Output

Boleh Disesuaikan

Output spider asas:

{
    "url": "https://www.example.com/page/",
    "title": "Tajuk Halaman Di Sini",
    "status": 200
}

Untuk crawl SEO, anda memerlukan medan yang serupa dengan apa yang dieksport oleh Screaming Frog:

def parse_page(self, response):
    yield {
        "url": response.url,
        "status": response.status,
        "title": response.css("title::text").get(),
        "meta_description": response.css("meta[name='description']::attr(content)").get(),
        "meta_robots": response.css("meta[name='robots']::attr(content)").get(),
        "h1": response.css("h1::text").get(),
        "canonical": response.css("link[rel='canonical']::attr(href)").get(),
        "og_title": response.css("meta[property='og:title']::attr(content)").get(),
        "og_description": response.css("meta[property='og:description']::attr(content)").get(),
        "word_count": len(response.text.split()) if response.status == 200 else None,
        "content_type": response.headers.get("Content-Type", b"").decode("utf-8", errors="ignore"),
    }

Tambah atau buang medan berdasarkan apa yang anda perlukan. Pemilih CSS berfungsi untuk mana-mana elemen pada halaman.

Format eksport: JSON (-o output.json), JSON Lines (-o output.jsonl), CSV (-o output.csv), XML (-o output.xml).

JSON Lines adalah terbaik untuk crawl besar. Fail adalah sah baris demi baris semasa crawl, jadi anda boleh memantau dengan tail -f. JSON standard tidak sah sehingga crawl selesai.

Screaming Frog → Scrapy

Panduan Terjemahan

Memetakan aliran kerja SF ke Scrapy:

Tindakan Screaming Frog Setara Scrapy
Mulakan crawl baru scrapy crawl spidername
Tetapkan kelewatan crawl DOWNLOAD_DELAY dalam tetapan
Hadkan thread serentak CONCURRENT_REQUESTS_PER_DOMAIN
Hormati robots.txt ROBOTSTXT_OBEY = True
Eksport ke CSV -o output.csv
Simpan/Muat crawl -s JOBDIR=crawl_state
Tapis subdomain Kod dalam spider (regex)
Pengekstrakan tersuai Pemilih CSS/XPath dalam parse()

Perubahan minda:

  1. Konfigurasi adalah kod. Edit settings.py daripada mengklik kotak pilihan.
  2. Pengekstrakan adalah eksplisit. Anda menulis data apa yang hendak ditangkap.
  3. Penjadualan adalah asli. Tambah arahan ke cron atau CI/CD.
  4. Nyahpepijat adalah log. Aktifkan AUTOTHROTTLE_DEBUG untuk melihat apa yang berlaku.

Aliran Kerja Penuh

Dengan tetapan standard di atas, anda boleh memasang Scrapy dan crawling dalam masa kurang 15 minit:

python3 -m venv venv
source venv/bin/activate  # venv\Scripts\activate pada Windows
pip install scrapy
scrapy startproject urlcrawler
cd urlcrawler
scrapy genspider mysite example.com
# Edit settings.py dengan config crawl sopan
# Edit spiders/mysite.py dengan logik parse anda
scrapy crawl mysite -o urls.jsonl -s JOBDIR=crawl_state

Scrapy Shell

Semasa anda membina konfigurasi tersuai, gunakan Scrapy Shell untuk menguji pemilih dan tetapan anda secara interaktif:

scrapy shell "https://example.com"

Ini membuka konsol Python interaktif dengan respons sudah dimuatkan. Uji pemilih CSS dan XPath dalam masa nyata sebelum menambahnya ke spider anda:

>>> response.css('title::text').get()
'Example Domain'
>>> response.xpath('//h1/text()').get()
'Example Domain'

Scrapy Shell mengurangkan masa iterasi dengan ketara. Sahkan logik pengekstrakan tanpa menjalankan crawl penuh.

Templat Spider Lengkap

Spider sedia pengeluaran dengan penapisan URL, pengendalian kod status, dan pengekstrakan medan SEO penuh:

import re
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from urllib.parse import urlparse


class SEOSpider(CrawlSpider):
    name = "seospider"
    allowed_domains = ["example.com"]
    start_urls = ["https://www.example.com"]

    # Capture all HTTP status codes, not just 2xx
    handle_httpstatus_list = [200, 301, 302, 403, 404, 500, 502, 503]

    # URL patterns to exclude
    EXCLUDED_PATTERNS = re.compile(
        r"/(in|au|th|es|hk|sg|ph|my|ca|cn|uk|kr|id|fr|vn|de|jp|nl|it|tw)/"
    )

    rules = (
        Rule(
            LinkExtractor(allow=()),
            callback="parse_page",
            follow=True,
            process_links="filter_links",
        ),
    )

    def filter_links(self, links):
        filtered = []
        for link in links:
            parsed = urlparse(link.url)
            hostname = parsed.hostname or ""

            if hostname not in ("example.com", "www.example.com"):
                continue

            if self.EXCLUDED_PATTERNS.search(link.url):
                continue

            filtered.append(link)
        return filtered

    def parse_page(self, response):
        yield {
            "url": response.url,
            "status": response.status,
            "title": response.css("title::text").get(),
            "meta_description": response.css("meta[name='description']::attr(content)").get(),
            "meta_robots": response.css("meta[name='robots']::attr(content)").get(),
            "h1": response.css("h1::text").get(),
            "canonical": response.css("link[rel='canonical']::attr(href)").get(),
            "og_title": response.css("meta[property='og:title']::attr(content)").get(),
            "og_description": response.css("meta[property='og:description']::attr(content)").get(),
            "word_count": len(response.text.split()) if response.status == 200 else None,
            "content_type": response.headers.get("Content-Type", b"").decode("utf-8", errors="ignore"),
        }

Gantikan example.com dengan domain sasaran anda. Sesuaikan EXCLUDED_PATTERNS untuk struktur URL laman anda.

Bila Guna Yang Mana

Screaming Frog:

Scrapy:

  • Laman melebihi 10,000 URL
  • Crawl automatik dan dijadualkan
  • Keperluan pengekstrakan tersuai
  • Integrasi CI/CD
  • Kekangan memori
  • Config versi terkawal

Kesimpulan

Scrapy mempunyai keluk persediaan yang lebih curam daripada Screaming Frog, tetapi ia menghapuskan had praktikal yang dikenakan oleh crawler GUI. Tiada had URL, tiada yuran lesen, penggunaan memori lebih rendah, dan automasi asli.

Mulakan kecil. Crawl laman yang anda kenali. Gunakan tetapan konservatif. Bandingkan output dengan Screaming Frog. Data akan sepadan, tetapi anda akan mempunyai alat yang berskala.