اول از همه: اصلاً دربارهٔ چه چیزی حرف میزنیم؟
گوگل ابزاری دارد به نام موتور جستجوی برنامهپذیر (Programmable Search Engine) — که پیشتر «موتور جستجوی سفارشی» یا Custom Search Engine نامیده میشد. با این ابزار میتوانید نسخهٔ کوچک و شخصیشدهٔ خودتان از گوگل را بسازید: موتوری که فقط در سایتهایی که شما تعیین میکنید جستجو کند.
در این آموزش، این مسیر سهمرحلهای را با هم طی میکنیم:
- مبتدی — موتور را میسازیم، دامنهها را وصل میکنیم و کلید دسترسی (API Key) میگیریم.
- متوسط — یاد میگیریم نتایج را با فیلترهای حرفهای مثل «فقط فایلهای PDF» یا «فقط مطالب ماه اخیر» دقیق کنیم.
- پیشرفته — جستجوها را لاگ میگیریم، کیفیت نتایج را میسنجیم و در یک حلقهٔ بازگشتی، موتور را مدام بهتر میکنیم.
بخش «برنامهپذیرِ» گوگل که با کد کار میکند، یعنی Custom Search JSON API، از سال ۲۰۲۵ برای مشتریان جدید بسته شده است؛ یعنی اگر تا به حال از آن استفاده نکردهاید، ممکن است نتوانید کلید تازهای برایش فعال کنید. همچنین گوگل اعلام کرده مشتریان فعلی تا ۱ ژانویهٔ ۲۰۲۷ فرصت دارند به راهکار دیگری کوچ کنند.
پس این آموزش برای شما همچنان کاملاً ارزشمند است، به دو دلیل:
- ساختِ خودِ موتور جستجو (بخش مبتدی، نسخهٔ ویجت/صفحهٔ آمادهٔ گوگل) هنوز باز و رایگان است و برای همه کار میکند.
- مفاهیم بخشهای متوسط و پیشرفته (فیلترها، لاگگیری، تحلیل و بهینهسازی) مفاهیمی جهانی هستند و عیناً روی جایگزینهای امروزی مثل Vertex AI Search یا سرویسهای مشابه هم قابل استفادهاند.
ما مسیر را با API رسمی گوگل توضیح میدهیم چون استانداردترین و آموزندهترین مرجع است؛ اما هرجا لازم باشد، جایگزین را هم یادآوری میکنیم. هیچگاه در گراول واقعیت را از شما پنهان نمیکنیم.
ساخت موتور، تنظیم دامنهها و گرفتن کلید API
وارد کنترلپنل موتور جستجو شوید
۳ دقیقهدر مرورگر این نشانی را باز کنید و با حساب گوگلتان وارد شوید:
https://programmablesearchengine.google.com/controlpanel/all
روی دکمهٔ افزودن / ساخت (Add / Create) کلیک کنید تا فرم ساخت موتور جدید باز شود.
Programmable Search Engine control panel را جستجو کنید؛ اولین نتیجهٔ رسمی گوگل همان کنترلپنل است.به موتورتان یک نام بدهید
۱ دقیقهدر فیلد نام موتور جستجو یک اسم گویا بنویسید؛ مثلاً «جستجوگر منابع پزشکی». این نام را هر زمان میتوانید عوض کنید.
دامنهها را تعیین کنید (قلب کار)
۴ دقیقهدر بخش چه چیزی جستجو شود؟ (What to search?) سایتهایی را که میخواهید موتور فقط داخل آنها بگردد، یکییکی وارد کرده و روی افزودن بزنید. میتوانید:
- کل یک سایت را اضافه کنید:
example.com - فقط یک بخش را اضافه کنید:
example.com/blog/* - چند سایت مختلف را کنار هم بگذارید.
wikipedia.org. وقتی دامنهای را اضافه میکنید، یعنی «فقط داخل این خانه بگرد».تنظیمات نهایی و ساخت
۲ دقیقهاگر خواستید، گزینههای جستجوی تصویر (Image search) و فیلتر محتوای امن (SafeSearch) را روشن کنید. سپس تیک «من ربات نیستم» را بزنید و روی ساخت (Create) کلیک کنید. تبریک — موتورتان ساخته شد!
شناسهٔ موتور (cx) را بردارید
۳ دقیقهوارد کنترلپنل موتورتان شوید. در بخش نمای کلی یا پایهای (Overview / Basics) عبارتی میبینید به نام Search engine ID. این یک رشتهٔ حروف و عدد است؛ آن را کپی کنید و جایی امن نگه دارید.
cx چیست؟ شناسهٔ موتور جستجوی شماست — مثل «شمارهٔ پلاک» موتورتان. هر وقت با کد بخواهید از این موتور استفاده کنید، باید همین شناسه را بفرستید تا گوگل بداند کدام موتور را صدا میزنید. در کدها معمولاً با نام cx ظاهر میشود.کلید دسترسی (API Key) بگیرید
۵ دقیقهبرای گرفتن کلید:
- به Google Cloud Console بروید و یک پروژه بسازید (یا پروژهٔ موجود را انتخاب کنید).
- سرویس Custom Search API را برای آن پروژه فعال کنید.
- به بخش Credentials (اعتبارنامهها) بروید و یک API Key بسازید.
اولین جستجوی واقعیتان
۴ دقیقهحالا دو چیز دارید: کلید (API Key) و شناسهٔ موتور (cx). این نشانی را بسازید و در مرورگر باز کنید (جاهای بزرگنوشته را با مقادیر خودتان جایگزین کنید):
# © Mehdi Rezghi — اولین درخواست جستجو
https://www.googleapis.com/customsearch/v1?key=YOUR_API_KEY&cx=YOUR_CX_ID&q=هوش+مصنوعی
اگر همهچیز درست باشد، مرورگر یک متنِ ساختاریافته به نام JSON نشانتان میدهد که پر از نتایج جستجوست.
"items"، "title" و "link" است، یعنی موتور و کلیدتان کار میکنند. 🎉 سطح مبتدی تمام شد.فیلترهای پیشرفته: نتایجِ دقیق بهجای نتایجِ زیاد
آناتومی یک درخواست را بشناسید
۴ دقیقههر درخواست جستجو از چند تکه ساخته میشود که با & به هم میچسبند:
https://www.googleapis.com/customsearch/v1
?key=API_KEY # کلید شما
&cx=CX_ID # شناسهٔ موتور شما
&q=SEARCH_TEXT # عبارت جستجو
&PARAM=VALUE # هر فیلتری که اضافه کنیم اینجا میآید
فیلتر زمان: dateRestrict
۵ دقیقهبا این پارامتر میگویید «فقط نتایج تازه را بده». مقدارش یک حرف (بازهٔ زمانی) بهعلاوهٔ یک عدد است:
| مقدار | معنی | مثال |
|---|---|---|
d[عدد] | این تعداد روزِ اخیر | dateRestrict=d7 → ۷ روز اخیر |
w[عدد] | این تعداد هفتهٔ اخیر | dateRestrict=w2 → ۲ هفتهٔ اخیر |
m[عدد] | این تعداد ماهِ اخیر | dateRestrict=m1 → ۱ ماه اخیر |
y[عدد] | این تعداد سالِ اخیر | dateRestrict=y1 → ۱ سال اخیر |
مثال حرفهای: «اخبار هوش مصنوعیِ فقط یک ماه اخیر»:
.../customsearch/v1?key=KEY&cx=CX&q=AI+news&dateRestrict=m1
فیلتر نوع فایل: fileType
۵ دقیقهمیخواهید فقط فایلهای خاصی برگردند؟ مثلاً فقط PDF یا فقط پاورپوینت؟ از این پارامتر استفاده کنید:
# فقط فایلهای PDF دربارهٔ «انرژی خورشیدی»
.../customsearch/v1?key=KEY&cx=CX&q=solar+energy&fileType=pdf
مقادیر پرکاربرد: pdf، doc، docx، ppt، xls، csv.
fileType=pdf و هم dateRestrict=y1 را کنار هم بگذارید.تمرکز روی یک سایت: siteSearch
۴ دقیقهگاهی میخواهید فقط داخل یک سایت خاص بگردید (یا برعکس، یک سایت را حذف کنید). دو پارامتر با هم کار میکنند:
| پارامتر | کار |
|---|---|
siteSearch | نام همان سایت؛ مثلاً siteSearch=who.int |
siteSearchFilter | i یعنی «فقط این سایت» — e یعنی «همهجا جز این سایت» |
# فقط نتایجِ داخل سایت who.int
&siteSearch=who.int&siteSearchFilter=i
مرتبسازی و صفحهبندی
۵ دقیقه| پارامتر | کار | نکته |
|---|---|---|
sort=date | نتایج را از تازهترین مرتب میکند | پیشفرض، مرتبسازی بر اساس ربط است |
num | تعداد نتایج هر صفحه | حداکثر ۱۰ — بیشتر ممکن نیست |
start | از کدام نتیجه شروع شود | برای صفحهٔ بعد: start=11 |
start نمیتواند از حدود ۹۱ بیشتر شود). اگر بیشتر میخواهید، باید عبارت جستجو را دقیقتر کنید، نه اینکه صفحهها را بیشتر ورق بزنید.فیلترهای کلمهای دقیق
۴ دقیقه| پارامتر | کار |
|---|---|
exactTerms | این عبارت حتماً در نتیجه باشد |
excludeTerms | این کلمه در نتیجه نباشد |
orTerms | دستکم یکی از این کلمهها باشد |
lr=lang_fa | فقط نتایج فارسی |
مثال حرفهای ترکیبی — «مقالهٔ PDF فارسیِ یک سال اخیر دربارهٔ یادگیری ماشین، ولی بدون کلمهٔ تبلیغاتی»:
.../customsearch/v1?key=KEY&cx=CX
&q=یادگیری+ماشین
&fileType=pdf
&dateRestrict=y1
&lr=lang_fa
&excludeTerms=تبلیغ
لاگگیری، تحلیل نتایج و بهینهسازی بازگشتی
پیشنیاز کوچک: پایتون و کتابخانهٔ درخواست
۴ دقیقهبرای لاگگیری خودکار، یک برنامهٔ کوچک پایتون مینویسیم. اگر پایتون ندارید، آموزش نصب پایتون در گراول موجود است. سپس این کتابخانه را نصب کنید:
# © Mehdi Rezghi — نصب کتابخانهٔ درخواستهای وب
pip install requests
requests چیست؟ ابزاری آمادهٔ پایتون که کار «صدا زدن یک نشانی اینترنتی و گرفتن پاسخ» را برایمان ساده میکند. بهجای کدهای پیچیده، فقط یک خط مینویسیم.یک جستجوگرِ لاگگیر بسازید
۸ دقیقهاین برنامه هر جستجو را انجام میدهد و نتیجهاش را در یک فایل CSV ذخیره میکند تا بعداً بتوانیم تحلیلش کنیم:
# © 2026 Mehdi Rezghi — https://t.me/Mehdirezghi
# جستجوگر لاگگیر گراول
import requests, csv, time
from datetime import datetime
API_KEY = "YOUR_API_KEY"
CX_ID = "YOUR_CX_ID"
ENDPOINT = "https://www.googleapis.com/customsearch/v1"
def search(query, **filters):
params = {"key": API_KEY, "cx": CX_ID, "q": query}
params.update(filters) # مثلاً fileType="pdf", dateRestrict="m1"
r = requests.get(ENDPOINT, params=params, timeout=15)
r.raise_for_status()
return r.json()
def log_search(query, **filters):
data = search(query, **filters)
total = data.get("searchInformation", {}).get("totalResults", "0")
items = data.get("items", [])
top3 = " | ".join(i.get("link", "") for i in items[:3])
with open("search_log.csv", "a", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow([
datetime.now().isoformat(timespec="seconds"),
query, str(filters), total, len(items), top3
])
print(f"✔ '{query}' → کل نتایج: {total} | برگشتی: {len(items)}")
if __name__ == "__main__":
log_search("یادگیری ماشین", fileType="pdf", dateRestrict="y1")
search_log.csv بسازد و در ترمینال خطی مثل «✔ 'یادگیری ماشین' → کل نتایج: ...» چاپ شود.چه چیزهایی را باید لاگ بگیریم؟
۴ دقیقهیک لاگ خوب باید بعداً به پرسشهایمان جواب بدهد. برای هر جستجو دستکم اینها را نگه دارید:
| ستون | چرا مهم است؟ |
|---|---|
| زمان | ببینیم کیفیت نتایج در طول زمان بهتر یا بدتر شده |
| عبارت جستجو + فیلترها | بفهمیم کدام ترکیبها بهترند |
| تعداد کل نتایج | خیلی کم = عبارت بیشازحد تنگ؛ خیلی زیاد = بیشازحد گشاد |
| سه نتیجهٔ اول | معیار سریعِ اینکه نتایج «مرتبط» بودهاند یا نه |
تحلیل: یک نتیجه چقدر «خوب» است؟
۶ دقیقهبرای سنجش کیفیت، دو معیار سادهٔ حرفهای کافی است:
- دقت (Precision): از ده نتیجهٔ اول، چند تا واقعاً به کار آمدند؟ اگر ۸ تا مفید بود، دقت شما ۸۰٪ است.
- نرخ نتیجهٔ خالی: چند درصد جستجوها هیچ نتیجهای برنگرداندند؟ اینها را باید بازطراحی کنید.
حلقهٔ بهینهسازی بازگشتی
۶ دقیقه«بهینهسازی بازگشتی» یعنی یک چرخهٔ تکرارشونده که هر دور، موتور را کمی بهتر میکند:
و بعد دوباره از قدم ۱ شروع میکنید. چند نمونه از «اصلاح» در قدم ۴:
| اگر دیدید… | این اصلاح را انجام دهید |
|---|---|
| نتایج نامرتبط زیادند | با exactTerms یا excludeTerms عبارت را تنگتر کنید |
| نتایج قدیمیاند | dateRestrict را سختگیرانهتر کنید (مثلاً از y1 به m3) |
| یک سایت مدام زباله میدهد | آن دامنه را از موتور حذف کنید |
| نتایج خیلی کماند | یک فیلتر را بردارید یا دامنههای مرتبط بیشتری اضافه کنید |
پایش سهمیه و مدیریت خطای فشار
۵ دقیقهپایش: در Google Cloud Console به بخش API Dashboard بروید تا مصرف روزانهتان را ببینید. برای پایش دقیقتر میتوانید در Cloud Operations روی سرویس customsearch.googleapis.com هشدار (Alert) تنظیم کنید.
خطای فشار (Rate limit): اگر زیادی سریع درخواست بفرستید، گوگل خطای 429 میدهد. راه درست، «عقبنشینی نمایی» است: کمی صبر کن، اگر باز خطا داد صبر را دو برابر کن.
# © Mehdi Rezghi — عقبنشینی نمایی هنگام خطای فشار
import time, requests
def safe_search(query, **filters):
delay = 1
for attempt in range(5):
try:
return search(query, **filters)
except requests.HTTPError as e:
if e.response.status_code == 429:
print(f"⏳ فشار زیاد؛ {delay} ثانیه صبر…")
time.sleep(delay)
delay *= 2 # 1 → 2 → 4 → 8 …
else:
raise
raise RuntimeError("بعد از چند تلاش، همچنان خطای فشار.")
🔧 رفع اشکالات رایج
API key not valid کلید را اشتباه کپی کردهاید یا سرویس Custom Search API را برای پروژه فعال نکردهاید. کلید را دوباره از Cloud Console بردارید و مطمئن شوید سرویس روشن است.Invalid Value برای cx شناسهٔ موتور را ناقص گذاشتهاید. آن را از بخش Overview/Basics کنترلپنل دوباره و کامل کپی کنید.items در پاسخ نیست یعنی جستجو نتیجهای نداشت. عبارت را گشادتر کنید، یک فیلتر را بردارید، یا مطمئن شوید دامنههای موتور محتوای مرتبط دارند.429 / quota exceeded به سقف ۱۰۰ جستجوی رایگانِ روزانه رسیدهاید. تا فردا (نیمهشب به وقت اقیانوس آرام) صبر کنید یا از کد «عقبنشینی نمایی» استفاده کنید.🎉 تمام شد! حالا شما بلدید…
- یک موتور جستجوی سفارشی بسازید و دامنههایش را تنظیم کنید.
- شناسهٔ موتور (cx) و کلید (API Key) بگیرید و اولین جستجو را بزنید.
- نتایج را با فیلترهای حرفهای مثل
dateRestrict،fileTypeوsiteSearchدقیق کنید. - جستجوها را لاگ بگیرید، دقتشان را بسنجید و در یک حلقهٔ بازگشتی، موتور را مدام بهتر کنید.
- سهمیه را پایش کنید و خطای فشار را حرفهای مدیریت کنید.
👣 مرحلهٔ بعدی پیشنهادی
حالا که میتوانید نتایج جستجو را برنامهوار بگیرید، قدم بعدی طبیعی این است: ساختِ یک «چت با اسناد» مبتنی بر RAG — که همین نتایج جستجو را به یک مدل هوش مصنوعی میدهد تا از دلشان پاسخ بسازد. یا اگر میخواهید همین جستجوگر را خودکار کنید، آموزش «ورکفلوی n8n: تلگرام → هوش مصنوعی» گام بعدی عالیای است. بگویید کدام را برایتان بسازم.