

گوگل مپ یکی از بزرگترین منابع اطلاعات مکانی و تجاری در اینترنت است. میلیونها کسبوکار در سراسر جهان اطلاعات خود را شامل نام، آدرس، شماره تماس، وبسایت، ساعت کاری، امتیاز کاربران و نظرات در Google Maps ثبت کردهاند. استخراج خودکار این دادهها میتواند برای تحلیل بازار، بررسی رقبا، تحقیقات محلی و پروژههای دادهمحور بسیار ارزشمند باشد.
در این مقاله، بهصورت گامبهگام یاد میگیریم چگونه با استفاده از زبان پایتون و ابزارهای اتوماسیون مرورگر، دادهها را از Google Maps استخراج کنیم. تمرکز این آموزش روی درک منطق اسکریپت، ساختار صفحه و پیادهسازی عملی است.
Web Scraping یا استخراج داده از وب، فرآیندی است که در آن اطلاعات موجود در صفحات وب بهصورت خودکار جمعآوری میشوند. بهجای کپی دستی دادهها، اسکریپتها و برنامهها این کار را انجام میدهند و خروجی ساختیافتهای مثل CSV یا JSON تولید میکنند.
وقتی صحبت از Google Maps میشود، به دلیل پویابودن صفحه و بارگذاری تدریجی دادهها، نمیتوان از روشهای ساده HTML Scraping استفاده کرد و نیاز به شبیهسازی رفتار کاربر واقعی داریم.

Google Maps یک وبسایت کاملاً داینامیک است. دادهها با JavaScript بارگذاری میشوند و ساخت URL جستجو نیز پیچیده است. به همین دلیل بهترین راهکار استفاده از ابزارهای Browser Automation مانند Selenium است.
Selenium امکان کنترل مرورگر واقعی را فراهم میکند و میتواند رفتار کاربر انسانی مثل تایپ، کلیک و اسکرول را شبیهسازی کند.
ابتدا مطمئن شوید Python 3 روی سیستم شما نصب شده است. سپس یک پوشه برای پروژه ایجاد کرده و محیط مجازی بسازید.
mkdir google-maps-scraper
cd google-maps-scraper
python -m venv envپس از فعالسازی محیط مجازی:
env/Scripts/activateبرای این پروژه از Selenium استفاده میکنیم. آن را با دستور زیر نصب کنید:
pip install seleniumدر فایل scraper.py ابتدا WebDriver کروم را در حالت Headless راهاندازی میکنیم.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
driver = webdriver.Chrome(
service=Service(),
options=options
)
در این مرحله مرورگر کنترلشده را به صفحه اصلی Google Maps هدایت میکنیم.
driver.get("https://www.google.com/maps")در برخی کشورها، گوگل پنجره پذیرش کوکیها را نمایش میدهد. برای جلوگیری از توقف اسکریپت، این مرحله را مدیریت میکنیم.
from selenium.webdriver.common.by import By
from selenium.common import NoSuchElementException
try:
accept_button = driver.find_element(By.CSS_SELECTOR, '[aria-label="Accept all"]')
accept_button.click()
except NoSuchElementException:
passاکنون باید عبارت موردنظر خود را در کادر جستجو وارد کنیم.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
search_input = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#searchboxinput"))
)
search_input.send_keys("italian restaurants")
search_button = driver.find_element(By.CSS_SELECTOR, 'button[aria-label="Search"]')
search_button.click()نتایج جستجو در ستون سمت چپ نمایش داده میشوند. این بخش بهصورت پویا بارگذاری میشود و باید منتظر آن بمانیم.
items = []
maps_items = WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located(
(By.XPATH, '//div[@role="feed"]//div[contains(@jsaction,"mouseover:pane")]')
)
)در این مرحله اطلاعات اصلی هر کسبوکار استخراج میشود.
import re
for maps_item in maps_items:
title = maps_item.find_element(
By.CSS_SELECTOR, "div.fontHeadlineSmall"
).text
link = maps_item.find_element(
By.CSS_SELECTOR, "a[jsaction][jslog]"
).get_attribute("href")
items.append({
"title": title,
"url": link
})در نهایت دادهها را در یک فایل CSV ذخیره میکنیم.
import csv
with open("items.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["title", "url"])
writer.writeheader()
for item in items:
writer.writerow(item)در پروژههای واقعی، اجرای اسکریپت بدون لاگگیری یک ریسک بزرگ است. اگر اسکریپت در میانه اجرا متوقف شود یا گوگل مپ ساختار صفحه را تغییر دهد، بدون لاگ تقریباً غیرممکن است بفهمید مشکل از کجاست.
با استفاده از ماژول logging در پایتون میتوان وضعیت اجرای اسکریپت، خطاها و مراحل مهم را ثبت کرد.
import logging
logging.basicConfig(
filename="scraper.log",
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logging.info("Script started")از این لاگها میتوانید برای دیباگ، مانیتورینگ و حتی تحلیل عملکرد اسکریپت استفاده کنید.
یکی از مشکلات رایج در Google Maps Scraping، خطاهای موقتی مانند Timeout یا لود نشدن المانهاست. بهجای توقف کامل اسکریپت، بهتر است مکانیزم Retry اضافه شود.
from selenium.common.exceptions import TimeoutException
import time
def safe_find(driver, by, value, retries=3):
for i in range(retries):
try:
return driver.find_element(by, value)
except TimeoutException:
time.sleep(2)
return Noneاین روش باعث میشود اسکریپت شما پایدارتر شود و در شرایط ناپایدار اینترنت بهطور کامل از کار نیفتد.
یکی از مشکلات جدی اسکریپهای Selenium این است که با کوچکترین تغییر در ساختار HTML، کل پروژه از کار میافتد. برای کاهش این ریسک، میتوان بررسی وجود المانها را شرطی کرد.
if driver.find_elements(By.CSS_SELECTOR, "div.fontHeadlineSmall"):
logging.info("Layout looks normal")
else:
logging.warning("Page layout may have changed")با این کار، در صورت تغییر ساختار صفحه، میتوانید سریعاً متوجه مشکل شوید و اسکریپت را بهروزرسانی کنید.
برای پروژههای بزرگ، ذخیره اطلاعات در CSV کافی نیست. استفاده از دیتابیس امکان جستجو، فیلتر و تحلیل دادهها را بسیار سادهتر میکند.
مثال ساده با SQLite:
import sqlite3
conn = sqlite3.connect("maps_data.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS places (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
address TEXT,
phone TEXT
)
""")
conn.commit()این کار پروژه شما را یک قدم به سمت سیستمهای دادهمحور واقعی نزدیک میکند.
بهجای اجرای اسکریپت فقط برای یک عبارت جستجو، میتوانید لیستی از شهرها یا دستهبندیها تعریف کنید.
queries = [
"coffee shop in Tehran",
"coffee shop in Shiraz",
"coffee shop in Isfahan"
]
for query in queries:
search_input.clear()
search_input.send_keys(query)
search_button.click()این قابلیت پروژه شما را از یک اسکریپت ساده به یک ابزار جمعآوری داده چندمنظوره تبدیل میکند.
یکی از ایدههای حرفهای، افزودن متادیتا به دادههای استخراجشده است. برای مثال میتوانید مشخص کنید هر داده مربوط به کدام شهر، کدام دستهبندی یا کدام تاریخ استخراج است.
item = {
"title": title,
"city": "Tehran",
"category": "Coffee Shop",
"scraped_at": datetime.now().isoformat()
}این کار در تحلیلهای بعدی و داشبوردهای داده بسیار ارزشمند خواهد بود.
با اضافه شدن این قابلیتها، نگهداری اسکریپت Selenium بهمرور پیچیدهتر و پرهزینهتر میشود. در چنین شرایطی استفاده از API آماده، هم از نظر زمان توسعه و هم از نظر پایداری، تصمیم هوشمندانهتری است.
سرویس AsanScrape این امکان را فراهم میکند که تمام این مراحل (مدیریت خطا، کپچا، تغییر ساختار صفحه و مقیاسپذیری) در لایه API انجام شود و شما فقط داده نهایی را دریافت کنید.
روشهایی که در این مقاله بررسی کردیم، یک مسیر کاملاً عملی برای استخراج داده از :contentReference[oaicite:0]{index=0} با استفاده از پایتون و Selenium هستند. این روشها برای یادگیری وباسکریپینگ، پروژههای تحقیقاتی، تست ایدهها و استخراج داده در مقیاس محدود بسیار مناسباند.
اما در سناریوهای واقعی و پروژههای بزرگتر، چالشهایی مانند مدیریت کپچا، تغییر ساختار DOM صفحات، محدودیت نرخ درخواستها (Rate Limit) و مسدود شدن IP میتوانند باعث شوند اسکریپتهای ساده بهسرعت ناکارآمد شوند.
برای کاهش ریسک شناسایی ربات، میتوان تنظیمات مرورگر را بهگونهای انجام داد که رفتار آن به کاربر واقعی نزدیکتر باشد. برای مثال:
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("--lang=en-US")
options.add_argument("--window-size=1920,1080")
options.add_argument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64)")این تنظیمات باعث میشوند Selenium کمتر شبیه یک ربات رفتار کند و احتمال بلاک شدن کاهش یابد. با این حال، حتی با این روشها نیز گوگل مپ در استفاده طولانیمدت محدودیتهایی اعمال میکند.
از آنجا که نتایج Google Maps بهصورت Lazy Load بارگذاری میشوند، باید اسکرول ستون نتایج را شبیهسازی کنیم:
import time
scrollable_div = driver.find_element(By.XPATH, '//div[@role="feed"]')
for i in range(5):
driver.execute_script(
"arguments[0].scrollTop = arguments[0].scrollHeight",
scrollable_div
)
time.sleep(3)با این کار، نتایج بیشتری بارگذاری میشوند و میتوان دادههای بیشتری از کسبوکارها استخراج کرد.
پس از کلیک روی هر آیتم، صفحه جزئیات باز میشود و میتوان اطلاعات کاملتری مانند شماره تماس، آدرس دقیق و ساعت کاری را استخراج کرد:
address = driver.find_element(
By.XPATH, '//button[@data-item-id="address"]'
).text
phone = driver.find_element(
By.XPATH, '//button[contains(@data-item-id,"phone")]'
).textاین مرحله معمولاً حساسترین بخش اسکریپت است، زیرا ساختار HTML در مناطق مختلف یا نسخههای مختلف Google Maps تغییر میکند.
اگر بخواهید هزاران یا میلیونها رکورد از Google Maps استخراج کنید، مدیریت مواردی مانند:
به یک چالش جدی تبدیل میشود و هزینه نگهداری اسکریپتها بهمرور افزایش مییابد. در این نقطه، استفاده از یک راهکار حرفهای منطقیتر است.
روشهایی که در این مقاله بررسی کردیم، از نظر آموزشی و پیادهسازی فنی بسیار مفید هستند و برای پروژههای کوچک، تست ایدهها و یادگیری وب اسکریپینگ انتخاب مناسبی محسوب میشوند. اما در دنیای واقعی و بهخصوص در پروژههای بزرگتر، این فرآیند با محدودیتها و چالشهای متعددی همراه است.
Google Maps بهصورت فعال از مکانیزمهای ضد ربات استفاده میکند و اجرای مداوم اسکریپتهای Selenium میتواند منجر به مسدود شدن IP، نمایش کپچا، کاهش سرعت پاسخدهی و حتی از کار افتادن کامل اسکریپت شود. علاوه بر این، تغییر مداوم ساختار صفحات باعث میشود نیاز به نگهداری و بهروزرسانی دائمی کدها وجود داشته باشد.
مدیریت مواردی مانند چرخش IP، حل کپچا، کنترل خطاها، مانیتورینگ اجرا و مقیاسپذیری، در نهایت زمان و هزینه توسعه پروژه را بهشدت افزایش میدهد و تمرکز تیم را از تحلیل دادهها دور میکند.
به همین دلیل، در بسیاری از پروژههای حرفهای و تجاری، بهجای پیادهسازی و نگهداری اسکریپتهای پیچیده، استفاده از سرویسهای آماده و تخصصی استخراج داده انتخاب منطقیتر و مقرونبهصرفهتری محسوب میشود.
اگر میخواهید استخراج داده از Google Maps را پایدار، سریع و بدون دردسرهای Selenium انجام دهید، بهترین راه این است که بهجای جنگیدن با کپچا، محدودیتها و تغییرات رابط گوگل، از یک API تخصصی استفاده کنید. با AsanScrape میتوانید خروجی ساختیافته بگیرید و تمرکزتان را روی تحلیل داده و کاربردهای کسبوکاری بگذارید—برای شروع، از اسکرپر نقشه گوگل استفاده کنید.
با استفاده از API اختصاصی AsanScrape میتوانید:
import requests
BASE_URL = "https://backend.asanscrape.com"
API_KEY = ""
url = f"{BASE_URL}/robots/create/task/wait-for-result/"
headers = {
"accept": "*/*",
"Authorization": f"token {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"robot": "google map advanced",
"inputs": {
"location": {
"latitude": 35.738314,
"longitude": 51.3338035,
"zoom": 13,
},
"keyword": "کافه",
"lang": "fa",
"country": "ir",
},
"pagination_token": "NEXT_TOKEN (optional)",
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
data = response.json()
print(data)در این مثال، با مشخص کردن موقعیت جغرافیایی (latitude/longitude/zoom) و یک کلیدواژه مثل «کافه»، ربات «google map advanced» نتایج را استخراج میکند. اگر دادهها چند صفحه باشند، میتوانید با مقدار pagination_token صفحه بعدی را هم دریافت کنید.
این روش برای تیمهای مارکتینگ، تحلیل بازار، تولید لید، و پروژههای دادهمحور که نیاز به خروجی قابل اتکا دارند، انتخابی حرفهای و مقرونبهصرفه است.
برای مشاهده مستندات کامل API و آشنایی با تمام قابلیتها، میتوانید اینجا را ببینید.