זחלן אתרים לאינדוקס תוכן פנימי
אנו בונים זחלנים מותאמים אישית שמאנדקסים את תוכן האתר שלכם באופן אוטומטי. הזחלנים שלנו עוברים על כל הדפים, מחלצים מטא-דאטה, ושומרים את התוצאות ב-PostgreSQL, Elasticsearch או Meilisearch כדי להפעיל חיפוש באתר, ביקורות תוכן וניתוח SEO. האספקה אורכת שלושה עד חמישה ימי עבודה. בנינו זחלנים לפורטלי תוכן, אתרי מסחר אלקטרוני ומאגרי ידע. הלקוחות שלנו משתמשים בנתונים המאונדקסים לחיפוש בזמן אמת, יצירת מפות אתר אוטומטיות ודוחות איכות תוכן קבועים.
כל אתר עתיר תוכן צריך לדעת מה הוא מכיל. זחלן מותאם אישית נותן לכם מפה מלאה ומובנית של האתר: כל כתובות ה-URL, הכותרות, התיאורים, הכותרות והטקסט. זה מאפשר חיפוש אתר מהיר יותר, זיהוי כפילויות אוטומטי, דוחות קישורים שבורים ואימות hreflang.
מה כלול בשירות פיתוח הזחלן שלנו
אנו מספקים את הזחלן כמערכת סוהר. ההיקף כולל:
- זחלן אסינכרוני באמצעות Python עם asyncio ו-httpx לסריקה במהירות גבוהה
- ניתוח HTML עם BeautifulSoup לחילוץ כותרת, תיאור, canonical, H1 וטקסט גוף
- בניית גרף קישורים לניתוח קישורים פנימיים
- הגבלת עומק ניתנת להגדרה, הגבלת דומיין ותבניות אי-הכללת URL
- אינטגרציית אחסון: PostgreSQL עם tsvector, Elasticsearch או Meilisearch
- מצב סריקה חוזרת מצטברת שמעבד רק דפים ששונו
- ממשק CLI להרצות ידניות ותזמון באמצעות cron
- דוח ריצה מפורט: דפים שנמצאו, שגיאות, שרשראות הפניות וסטטיסטיקות אינדוקס
למה לבנות זחלן מותאם אישית במקום להשתמש בכלים מוכנים?
זחלנים לשימוש כללי כמו Screaming Frog מייצאים קבצי CSV. הם לא משתלבים עם בסיס הנתונים של היישום שלכם. הם לא יכולים לדחוף תוכן חדש לאינדקס החיפוש בזמן אמת. הם לא יודעים אילו סוגי תוכן חשובים למקרה השימוש הספציפי שלכם.
זחלן מותאם אישית קורא את האתר שלכם וכותב נתונים מובנים בדיוק למקום שהיישום שלכם צריך אותם. הוא רץ על התשתית שלכם, מכבד את האימות ומגבלות הקצב שלכם, ומייצר את סכמת הנתונים המדויקת שהצוות שלכם תכנן. בונים פעם אחת, מריצים לפי לוח זמנים, ללא רישיונות מושב.
ארכיטקטורה טכנית
הזחלן בנוי כיישום Python אסינכרוני. הוא מנהל תור frontier של כתובות URL ממתינות, עוקב אחר כתובות שביקרו בהן כדי למנוע כפילויות, ומעבד דפים במקביל עם מגבלת מקביליות ניתנת להגדרה.
import asyncio
import httpx
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
from collections import defaultdict
class SiteCrawler:
def __init__(self, base_url: str, max_pages: int = 10000):
self.base_url = base_url
self.base_domain = urlparse(base_url).netloc
self.max_pages = max_pages
self.visited = set()
self.queue = asyncio.Queue()
self.results = []
async def crawl(self) -> list:
await self.queue.put(self.base_url)
async with httpx.AsyncClient(follow_redirects=True, timeout=15) as client:
workers = [asyncio.create_task(self._worker(client)) for _ in range(5)]
await self.queue.join()
for w in workers:
w.cancel()
return self.results
async def _worker(self, client: httpx.AsyncClient):
while True:
url = await self.queue.get()
try:
if url in self.visited or len(self.visited) >= self.max_pages:
continue
self.visited.add(url)
resp = await client.get(url)
page_data = self._parse_page(url, resp)
self.results.append(page_data)
if resp.status_code == 200 and 'text/html' in resp.headers.get('content-type', ''):
for link in page_data['internal_links']:
if link not in self.visited:
await self.queue.put(link)
finally:
self.queue.task_done()
def _parse_page(self, url: str, resp: httpx.Response) -> dict:
soup = BeautifulSoup(resp.text, 'lxml') if resp.status_code == 200 else None
result = {
'url': url,
'status': resp.status_code,
'title': soup.select_one('title')&.get_text(strip=True) if soup else None,
'h1': soup.select_one('h1')?.get_text(strip=True) if soup else None,
'canonical': soup.select_one('link[rel=canonical]')?.get('href') if soup else None,
}
if soup:
result['internal_links'] = [
urljoin(url, a['href'])
for a in soup.find_all('a', href=True)
if urlparse(urljoin(url, a['href'])).netloc == self.base_domain
]
return result
שמירה לאינדקס חיפוש
התוצאות נשלחות לקצה החיפוש שהצוות שלכם מעדיף. עבור חיפוש טקסט מלא ב-PostgreSQL:
CREATE TABLE page_index (
url TEXT PRIMARY KEY,
title TEXT,
description TEXT,
h1 TEXT,
body_text TEXT,
tsv tsvector GENERATED ALWAYS AS (
to_tsvector('english', coalesce(title, '') || ' ' || coalesce(description, '') || ' ' || coalesce(body_text, ''))
) STORED,
crawled_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX ON page_index USING gin(tsv);עבור Meilisearch, התוצאות נדחפות באמצעות לקוח Python לאחר כל ריצת סריקה. Meilisearch מטפל בסובלנות שגיאות כתיב ובסינון פאקטות ללא צורך בהגדרה נוספת.
איך עובדת סריקה מצטברת?
סריקות אתר מלאות יכולות לארוך דקות באתרים גדולים. מצב מצטבר מביא רק דפים שבהם התוכן השתנה מאז הסריקה האחרונה. אנו מזהים שינויים על ידי השוואת כותרת ETag או Last-Modified בתגובה, או על ידי חישוב checksum של הטקסט שחולץ. דפים ששונו עוברים אינדוקס מחדש; דפים שלא השתנו נדלגים.
זה הופך את הזחלן למתאים להרצה לפי לוח זמנים כל שעה ללא עומס יתר על השרת.
אילו דוחות הזחלן מייצר?
לאחר כל ריצה הזחלן מייצר דוח מובנה:
- סך הדפים שנסרקו ומשך הסריקה
- פילוח שגיאות HTTP: דפי 404, שגיאות 500, שרשראות הפניות ארוכות משני קפיצים
- דפים חסרי כותרת, תיאור או H1
- קבוצות כותרת ותיאור כפולים
- סטטיסטיקות גרף קישורים פנימיים: דפים ללא קישורים נכנסים, דפים עם יותר מדי קישורים יוצאים
| היקף | לוח זמנים |
|---|---|
| זחלן עם אינדקס PostgreSQL | 3–5 ימי עבודה |
| זחלן עם Meilisearch ולוח בקרה | 5–7 ימי עבודה |
| זחלן מצטבר עם זיהוי שינויים | 4–6 ימי עבודה |
צרו קשר כדי לדון בדרישות האינדוקס שלכם. נבדוק את מבנה האתר שלכם, נבחר את הטכנולוגיה המתאימה, ונספק זחלן עובד עם תיעוד והוראות פריסה.







