پرش به محتویات

داده‌های ترافیکی و استفاده از Mapbox

داده‌های ترافیکی به‌عنوان بخشی از داده‌های جابه‌جایی محسوب می‌شوند. با توجه به استفاده گسترده از نقشه‌های ترافیکی آنلاین، می‌توان نتیجه گرفت که داده‌های ترافیکی برای کشور ایران نیز در دسترس هستند. با این حال، دسترسی به این داده‌ها به‌راحتی امکان‌پذیر نیست، زیرا شرکت‌هایی نظیر گوگل و بینگ از این اطلاعات به‌عنوان منابع درآمدی خود بهره‌برداری می‌کنند و به‌طور رایگان آن‌ها را در اختیار عموم قرار نمی‌دهند.

اگرچه داده‌های ترافیکی جزو اطلاعات محرمانه به‌شمار نمی‌روند، اما در کشور ما دسترسی به آن‌ها به‌سادگی فراهم نیست. یکی از سرویس‌هایی که می‌توانیم برای دسترسی به این داده‌ها استفاده کنیم، Mapbox است که امکان دریافت داده‌های ترافیکی را به‌طور آنلاین و آسان فراهم می‌آورد.

معرفی Mapbox

سایت Mapbox یکی از پیشرفته‌ترین پلتفرم‌های نقشه‌سازی و تجزیه و تحلیل داده‌های جغرافیایی است. این پلتفرم ابزارهایی را برای ایجاد نقشه‌های تعاملی، تحلیل داده‌های جغرافیایی و افزودن ویژگی‌هایی مانند ترافیک، حمل‌ونقل، و داده‌های مکان‌محور فراهم می‌کند.

یکی از ویژگی‌های برجسته Mapbox، قابلیت دریافت داده‌های ترافیکی در زمان واقعی است. این ویژگی به کاربران این امکان را می‌دهد که وضعیت ترافیک جاده‌ها را به‌صورت زنده و با دقت بالا مشاهده کنند.

برای استفاده از خدمات Mapbox Traffic v1 یا سایر داده‌های جغرافیایی این پلتفرم، می‌توانید به سایت رسمی Mapbox مراجعه کنید:
Mapbox Official Site

استفاده از API Mapbox

با استفاده از API Mapbox، می‌توان به‌راحتی داده‌های ترافیکی را از سرویس‌های Mapbox دریافت کرد. برای دسترسی به لایه‌های داده از طریق Vector Tiles API، می‌توان از الگوی زیر استفاده نمود:

https://api.mapbox.com/v4/mapbox.mapbox-traffic-v1/{z}/{x}/{y}.{format}?access_token=YOUR_ACCESS_TOKEN

در این URL، {z}، {x} و {y} نمایانگر مقادیر مربوط به موقعیت جغرافیایی هستند. با تغییر این مقادیر، می‌توان داده‌های مورد نظر را دریافت کرد.

وکتور تایل‌ها (Vector Tiles)

وکتور تایل‌ها یک فرمت برای ذخیره‌سازی و انتقال داده‌های جغرافیایی هستند که در نمایش نقشه‌ها در وب و اپلیکیشن‌های موبایل استفاده می‌شوند. برخلاف رستر تایل‌ها که تصاویر ثابت هستند، وکتور تایل‌ها از داده‌های جغرافیایی به‌صورت وکتوری (شکل‌ها و خطوط) استفاده می‌کنند. این امر این امکان را فراهم می‌آورد که نقشه‌ها به‌صورت پویا و با کیفیت بالا روی دستگاه‌های مختلف بارگذاری و تغییر اندازه داده شوند.

وکتور تایل‌ها برای پروژه‌هایی که نیاز به نقشه‌های تعاملی و پویا دارند بسیار مناسب هستند و در مقایسه با رستر تایل‌ها مزایای زیادی دارند. در سرویس‌هایی مانند Mapbox و Google Maps، این نوع تایل‌ها به‌طور گسترده استفاده می‌شوند.

داده‌های ترافیکی Mapbox

داده‌های ترافیکی Mapbox به‌صورت کیفی و پویا در دسترس هستند و به‌طور مداوم وضعیت ترافیک در جاده‌ها را در زمان واقعی نشان می‌دهند. این داده‌ها به کاربران این امکان را می‌دهند که وضعیت ترافیک را در سطح جاده‌ها، خیابان‌ها و بزرگراه‌ها مشاهده کنند.

اطلاعات کیفی ترافیک

داده‌های ترافیکی Mapbox به‌طور عمده به‌صورت کیفی نمایش داده می‌شوند، به این معنا که وضعیت کلی ترافیک به‌صورت رنگ‌ها و شاخص‌های قابل‌درک به نمایش درمی‌آید.

نمونه URL برای دریافت داده‌های ترافیکی از Mapbox

برای دریافت داده‌ها از سرویس ترافیک Mapbox Traffic v1، می‌توانید از URL زیر استفاده کنید:

https://api.mapbox.com/v4/mapbox.mapbox-traffic-v1.json?access_token=YOUR_ACCESS_TOKEN

در اینجا، YOUR_ACCESS_TOKEN باید با توکن دسترسی واقعی شما جایگزین شود.

نحوه دریافت Access Token از Mapbox

  1. ساخت حساب کاربری در Mapbox
    ابتدا باید یک حساب کاربری در Mapbox ایجاد کنید. برای این منظور، به سایت Mapbox مراجعه کرده و یک حساب کاربری جدید بسازید:
    Mapbox Signup

  2. ورود به حساب کاربری
    پس از ایجاد حساب کاربری، وارد حساب خود شوید.

  3. دریافت Access Token
    بعد از ورود به حساب کاربری، مراحل زیر را دنبال کنید:

  4. به صفحه Account یا Dashboard بروید.
  5. در این صفحه، گزینه‌ای به نام Access Tokens خواهید دید. روی آن کلیک کنید.

Bounding Box چیست؟

یک مفهوم مهم در جغرافیا و داده‌های جغرافیایی است. این مستطیل، منطقه‌ای را روی نقشه مشخص می‌کند که با استفاده از مختصات جغرافیایی (عرض و طول جغرافیایی) آن را محدود می‌کنیم. به‌عبارت‌دیگر، Bounding Box یک ناحیه جغرافیایی را تعریف می‌کند که از چهار مرز تشکیل شده است:

عرض جغرافیایی پایین (South Latitude)

عرض جغرافیایی بالا (North Latitude)

طول جغرافیایی چپ (West Longitude)

طول جغرافیایی راست (East Longitude))

برای تعیین Bounding Box می‌توانید از سایت bboxfinder.com استفاده کنید. این ابزار به شما این امکان را می‌دهد که یک ناحیه خاص را روی نقشه انتخاب کرده و مختصات دقیق آن را به دست آورید.

مراحل استفاده از پلی‌گون در bboxfinder.com:

  1. باز کردن سایت: ابتدا به سایت bboxfinder.com بروید.
  2. انتخاب ابزار کشیدن پلی‌گون: در سایت، ابزارهای مختلفی برای انتخاب منطقه وجود دارد. یکی از این ابزارها، ابزار Polygon است که به شما اجازه می‌دهد با کشیدن یک پلی‌گون، منطقه خاصی را بر روی نقشه مشخص کنید.
  3. کشیدن پلی‌گون: برای استفاده از این ابزار، کافی است که در نقشه روی نقاط مختلف کلیک کنید تا یک پلی‌گون بسازید. نقاطی که انتخاب می‌کنید، به ترتیب به هم وصل می‌شوند تا محدوده مورد نظر شما تشکیل شود.

الگوی URL برای درخواست داده‌ها از Mapbox

https://api.mapbox.com/v4/mapbox.mapbox-traffic-v1.json?access_token=YOUR_ACCESS_TOKEN&bbox={}&zoom={}

در این URL، bbox={} و zoom={} به‌عنوان پارامترهایی برای تعیین محدوده جغرافیایی (Bounding Box) و میزان بزرگنمایی (Zoom) در نقشه استفاده می‌شوند.

مثال Bounding Box:

BBOX = (51.376259, 35.700060, 51.457455, 35.741859)
در این مثال، مختصات طول و عرض جغرافیایی برای تعیین محدوده جغرافیایی مشخص شدهاند:

طول جغرافیایی پایین (West Longitude): 51.376259

عرض جغرافیایی پایین (South Latitude): 35.700060

طول جغرافیایی بالا (East Longitude): 51.457455

عرض جغرافیایی بالا (North Latitude): 35.741859

کد کامل برای دریافت داده‌های ترافیکی از Mapbox

import os
import requests
import geopandas as gpd
import pandas as pd
import mercantile

BBOX = (51.376259, 35.700060, 51.457455, 35.741859)
ZOOM = 14
OUT_DIR = os.path.join('data', 'traffic')
os.makedirs(OUT_DIR, exist_ok=True)

tile_ul = mercantile.tile(BBOX[0], BBOX[3], ZOOM)
tile_lr = mercantile.tile(BBOX[2], BBOX[1], ZOOM)

x_min, x_max = min(tile_ul.x, tile_lr.x), max(tile_ul.x, tile_lr.x)
y_min, y_max = min(tile_ul.y, tile_lr.y), max(tile_ul.y, tile_lr.y)

# URL Template درست برای درخواست تایل‌ها از Mapbox
URL_Template = 'https://api.mapbox.com/v4/mapbox.mapbox-traffic-v1/{z}/{x}/{y}.mvt?access_token=YOUR_ACCESS_TOKEN'

for x in range(x_min, x_max + 1):
    for y in range(y_min, y_max + 1):
        url = URL_Template.format(z=ZOOM, x=x, y=y)

        outfile = os.path.join(OUT_DIR, f"{ZOOM}_{x}_{y}.mvt")

        try:
            resp = requests.get(url, headers=None, timeout=15)

            if resp.status_code == 200 and resp.content:
                with open(outfile, 'wb') as f:
                    f.write(resp.content)
            else:
                print(f"[WARN] {resp.status_code}: {url}")
        except Exception as e:
            print(f"[ERROR] {e}: {url}")

gdfs = []
for file in os.listdir(OUT_DIR):
    if file.endswith('.mvt'):
        mvt_path = os.path.join(OUT_DIR, file)
        gdf = gpd.read_file(mvt_path)
        gdfs.append(gdf)

merge_gdfs = gpd.GeoDataFrame(pd.concat(gdfs, ignore_index=True), crs=gdfs[0].crs)
merge_gdfs.to_file(os.path.join(OUT_DIR, 'traffic.shp'))

ساخت پوشه مقصد در صورت عدم وجود:

os.makedirs(OUT_DIR, exist_ok=True)

این خط از کد بررسی می‌کند که آیا پوشه data/traffic وجود دارد یا خیر. اگر وجود نداشته باشد، آن را می‌سازد. گزینه exist_ok=True باعث می‌شود اگر پوشه قبلاً وجود داشته باشد، خطا ندهد.

تبدیل مختصات به تایل‌ها:

tile_ul = mercantile.tile(BBOX[0], BBOX[3], ZOOM)
tile_lr = mercantile.tile(BBOX[2], BBOX[1], ZOOM)

در اینجا با استفاده از کتابخانه mercantile، مختصات گوشه بالا سمت چپ و پایین سمت راست Bounding Box (مستطیل محصور) به تایل‌های Web Mercator تبدیل می‌شوند. این تبدیل به ما این امکان را می‌دهد که داده‌ها را به صورت تایل‌های کوچک از Mapbox درخواست کنیم.

BBOX[0]: طول جغرافیایی غرب (minimum longitude).

BBOX[1]: عرض جغرافیایی پایین (minimum latitude).

BBOX[2]: طول جغرافیایی شرق (maximum longitude).

BBOX[3]: عرض جغرافیایی بالا (maximum latitude).

محاسبه مرزهای تایل‌ها:

x_min, x_max = min(tile_ul.x, tile_lr.x), max(tile_ul.x, tile_lr.x)
y_min, y_max = min(tile_ul.y, tile_lr.y), max(tile_ul.y, tile_lr.y)

این کد مرزهای افقی و عمودی تایل‌ها را محاسبه می‌کند. برای مثال، اگر چندین تایل در منطقه خاصی نیاز داریم، این خطوط مرزهای آن تایل‌ها را مشخص می‌کند.

در این خط، یک قالب URL برای دریافت داده‌های ترافیکی از Mapbox تعریف می‌شود. با استفاده از این URL می‌توان داده‌های ترافیکی مربوط به هر تایل را دریافت کرد. پارامترهای bbox و zoom به ترتیب مربوط به محدوده جغرافیایی و سطح بزرگنمایی هستند.

درخواست داده‌ها از Mapbox

for x in range(x_min, x_max + 1):
    for y in range(y_min, y_max + 1):
        url = URL_Template.format(z=ZOOM, x=x, y=y)
        outfile = os.path.join(OUT_DIR, f"{ZOOM}_{x}_{y}.mvt")

در این حلقه‌های for، برای هر تایل در منطقه مشخص‌شده، یک درخواست به Mapbox ارسال می‌شود. x و y مختصات افقی و عمودی هر تایل هستند. سپس داده‌ها برای هر تایل در فایل‌های .mvt ذخیره می‌شوند.

ارسال درخواست HTTP به Mapbox:

resp = requests.get(url, headers=None, timeout=15)

در این خط، درخواست GET به Mapbox ارسال می‌شود تا داده‌های ترافیکی برای تایل خاص دریافت شود. همچنین برای جلوگیری از وقفه‌های طولانی، زمان تایم‌اوت 15 ثانیه تعیین شده است.

بررسی وضعیت پاسخ و ذخیره داده‌ها:

if resp.status_code == 200 and resp.content:
    with open(outfile, 'wb') as f:
        f.write(resp.content)

اگر پاسخ موفقیت‌آمیز باشد (کد وضعیت 200) و داده‌ها وجود داشته باشند، این داده‌ها در فایلی که نامش شامل سطح زوم و شماره تایل است ذخیره می‌شود.

مدیریت خطاها:

else:
    print(f"[WARN] {resp.status_code}: {url}")

اگر درخواست به Mapbox موفقیت‌آمیز نباشد، کد وضعیت و URL درخواست چاپ می‌شود تا بتوان دلیل مشکل را شناسایی کرد.

مدیریت استثناها:

except Exception as e:
    print(f"[ERROR] {e}: {url}")

در صورتی که خطایی در طول ارسال درخواست یا ذخیره‌سازی فایل پیش آید، پیام خطا همراه با URL درخواست چاپ می‌شود تا بتوان خطا را پیگیری کرد.

خواندن و پردازش داده‌های .mvt:

gdfs = []
for file in os.listdir(OUT_DIR):
    if file.endswith('.mvt'):
        mvt_path = os.path.join(OUT_DIR, file)
        gdf = gpd.read_file(mvt_path)
        gdfs.append(gdf)

تمام فایل‌های .mvt که در پوشه OUT_DIR ذخیره شده‌اند خوانده می‌شوند و به یک لیست از GeoDataFrame‌ها (gdfs) اضافه می‌شوند. این داده‌ها بعداً برای ترکیب استفاده خواهند شد.

ترکیب داده‌ها در یک GeoDataFrame:

merge_gdfs = gpd.GeoDataFrame(pd.concat(gdfs, ignore_index=True), crs=gdfs[0].crs)

تمام GeoDataFrame‌های خوانده‌شده از فایل‌های .mvt به یک GeoDataFrame واحد ترکیب می‌شوند. این ترکیب به ما این امکان را می‌دهد که تمام داده‌ها را در یک مجموعه داشته باشیم.

ذخیره داده‌های نهایی به‌صورت Shapefile:

merge_gdfs.to_file(os.path.join(OUT_DIR, 'traffic.shp'))

در نهایت، داده‌های ترکیب‌شده به فرمت Shapefile ذخیره می‌شوند.