گردآوری داده ها برای علم داده در پایتون — راهنمای کاربردی

۳۵۰ بازدید
آخرین به‌روزرسانی: ۳۰ آبان ۱۴۰۲
زمان مطالعه: ۱۰ دقیقه
گردآوری داده ها برای علم داده در پایتون — راهنمای کاربردی

«داده‌کاوی» (Data Mining) و «تحلیل داده‌ها» (Data Analysis) به صورت فرایندی انجام می‌شوند؛ بدین معنا که دارای چندین گام هستند و در یک گام شروع و پایان نمی‌پذیرند. یکی از گام‌های مهم در این راستا و از ابتدایی‌ترین گام‌ها، گردآوری داده‌ها (Data Gathering) است. در این مطلب، چند «رابط برنامه‌نویسی کاربردی» (Application Programming Interface | API) به منظور گردآوری داده ها برای علم داده در پایتون معرفی و روش کار با آن‌ها به طور کامل و همراه با ارائه مثال‌هایی، آموزش داده شده است.

گردآوری داده ها برای علم داده در پایتون

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

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

روش استفاده از رابط‌های برنامه‌نویسی کاربردی برای گردآوری داده ها

در این راهنما، در ابتدا روش گردآوری داده‌ها بدون نیاز به احراز هویت مورد بررسی قرار می‌گیرد.سپس، رابط‌های برنامه‌نویسی کاربردی دیگری مورد بررسی قرار می‌گیرند که برای انجام کار نیاز به احراز هویت کاربر دارند. بررسی موردی اولی که در این مطلب مطرح شده است، مربوط به پیدا کردن محل کنونی قرارگیری «ایستگاه بین‌المللی فضایی» (International Space Station | ISS) است. در این راستا از Open Notify API استفاده شده است. سپس، در یک بررسی موردی دیگر، به منظور گردآوری داده‌های آب و هوایی، از رابط برنامه‌نویسی کاربردی آب و هوا با عنوان Dark Sky استفاده شده است. آنچه بیان شد، مثالی از گردآوری داده‌ها همراه با احراز هویت است. در نهایت، به بررسی چگونگی گردآوری داده‌های «بورس فرانکفورت» (Frankfurt Stock Exchange) در یک «چارچوب داده» (Data Frame) کتابخانه «پانداس» (Pandas) پرداخته شده است. شایان توجه است که پانداس یکی از کتابخانه‌های بسیار محبوب «زبان برنامه‌نویسی پایتون» (Python Programming Language) به ویژه در حوزه «علم داده» (Data Science) است.

روش کار API‌ها

هنگامی که کاربر قصد دارد داده‌ها را از یک رابط برنامه‌نویسی کاربردی دریافت کند، باید یک درخواست (Request) از سرور ایجاد کند. به منظور قادر شدن به کشیدن داده‌ها از یک API با استفاده از پایتون، نیاز به استفاده از کتابخانه پایتون Requests است.

Requests یک بسته استاندارد برای ایجاد درخواست‌های HTTP در پایتون است. کار با این بسته به دلیل سطحی از انتزاع که دارد، به ویژه هنگام کار با با رابط‌های برنامه‌نویسی کاربردی، بسیار ساده است. برای شروع به کار، کاربر ممکن است نیاز به نصب کتابخانه Requests داشته باشد. زیرا این کتابخانه، بخشی از بسته استاندارد پایتون نیست. این کار را می‌توان با استفاده از مدیر بسته پایتون «کوندا» (Conda) یا pip انجام داد.

1pip install requests
2conda install requests

یک درخواست از چهار بخش متفاوت ساخته شده است. هر یک از این بخش‌ها در ادامه بیان و معرفی شده‌اند.

  • یک نقطه انتهایی (Endpoint): این مورد مانند URL برای داده‌ها است.
  • یک متد (Method): شامل POST ،PUT ،GET یا DELETE می‌شود. در این مطلب، صرفا از GET requests استفاده شده است.
  • سرآیندها (Headers): این موارد شامل فراهم کردن اطلاعاتی شامل کلیدهای احراز هویت است.
  • داده/بدنه: این مورد بخشی از GET request نیست.

هنگامی که یک درخواست با استفاده از کتابخانه Request اجرا می‌شود، یک شی درخواست باز می‌گرداند. این شی شامل داده‌هایی که انتظار می‌رود استخراج شوند، و همچنین یک کد وضعیت (Status Code) است. کد وضعیت نشان می‌دهد که چه اتفاقی برای درخواست افتاده است و این موارد به عنوان بخشی از هر درخواست محسوب می‌شوند. در اینجا از GET requests و تعدادی از کدهای پاسخی که مربوط به کار است، استفاده می‌شود. کدها، بسته به اطلاعاتی که باز می‌گردانند، به مقادیر گوناگونی بر مبنای صد، تقسیم می‌شوند. این کدها در ادامه شرح داده شده‌اند.

  • 1xx: فراهم کردن اطلاعات
  • 2xx: موفقیت‌آمیز بودن امور
  • 3xx: فراهم کردن اطلاعات پیرامون ریدایرکت‌ها
  • 4xx: به خطای کارخواه (کلاینت | Client) اشاره دارد (خطای ما).
  • 5xx: به خطای کارگزار (سرور | Server) اشاره دارد (خطای آن‌ها).

اغلب افراد با خطای ۴۰۴ آشنایی دارند. این خطا هنگامی نمایش داده می‌شود که صفحه وب پیدا نمی‌شود. این در واقع همان کد وضعیت (Status Code) است. به طور مشابه، کد وضعیت ۲۰۰ به کاربر این امکان را می‌دهد که بداند همه چیز مناسب است. این همان کد وضعیتی است که کاربر باید دریافت کند.

بررسی موردی جهت آموزش کار با Open Notify API

در اولین بخش از این مطلب، نگاهی به Open Notify API انداخته می‌شود. این رابط برنامه‌نویسی کاربردی، داده‌های ایستگاه فضایی بین المللی را فراهم می‌کند. برای کسب اطلاعات بیشتر پیرامون جزئیات این API، باید مستندات آن را بررسی کرد. در ادامه، روش کار با این API مورد بررسی قرار می‌گیرد. یکی از ویژگی‌های خوب این رابط برنامه‌نویسی کاربردی آن است که نیاز به احراز هویت ندارد؛ بدین معنا که می‌توان به طور مستقیم به کار کشیدن (Pulling) داده‌ها پرداخت، بدون اینکه نیاز به تنظیمات و راه‌اندازی‌های خاصی باشد. کار با تولید یک URL request با کتابخانه Requests و دسترسی به خصیصه کد وضعیت (Status Code) آن آغاز می‌شود. این کار را می‌توان با خط کدهای ارائه شده در زیر انجام شده است.

1import requests
2response = requests.get("http://api.open-notify.org/iss-now.json")
3print(response.status_code)

خروجی قطعه کد بالا به صورت زیر است.

200

تابع get()‎. یک شی request را درخواست می‌کند. در اینجا، از خصیصه status_code‎. برای کشف آنچه کد وضعیت را باز می‌گرداند، استفاده شده است. در این مثال، status_code بازگردانده شده ۲۰۰ است، این یعنی همه کارها به صورت مناسبی پیش رفته است و می‌توان گامی رو به جلو برداشت.

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

1import requests
2import json
3response = requests.get("http://api.open-notify.org/iss-now.json")
4print(response.json())

خروجی قطعه کد بالا به صورت زیر است.

{'message': 'success', 'timestamp': 1583154620, 
 'iss_position': {'longitude': '-28.1832', 'latitude': '7.4263'}}

رشته‌ای که این پاسخ باز می‌گرداند، کاملا کوتاه و خواندن آن آسان است. اگرچه، بسیاری از پاسخ‌های رابط برنامه‌نویس کاربردی طولانی هستند و ممکن است نیازمند اندکی تجزیه برای جایی باشند که کاربر نیاز به بررسی داده‌ها دارد (در واقع اگر کاربر علاقه‌مند به بررسی بخش خاصی از داده‌ها است). در ادامه از تابع dumps()‎. برای تبدیل رشته JSON به شی پایتون استفاده شده است. در ادامه، برخی از کدها برای استمرار تکرار شده‌اند.

1response = requests.get("http://api.open-notify.org/iss-now.json")
2json_response = response.json()
3dictionary = json.dumps(response.json(), sort_keys = True, indent = 4)
4print(dictionary)

خروجی قطعه کد بالا به صورت زیر است.

{
    "iss_position": {
        "latitude": "29.2380",
        "longitude": "-117.4817"
    },
    "message": "success",
    "timestamp": 1583170890
}

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

1response = requests.get("http://api.open-notify.org/iss-now.json")
2json_response = response.json()
3longitude = json_response['iss_position']['longitude']
4latitude = json_response['iss_position']['latitude']
5print('Longitude: ', longitude)
6print('Latitude: ', latitude)

خروجی قطعه کد بالا به صورت زیر است.

Longitude:  -28.1832
Latitude:  7.4263

یک مسئله مهم که باید به آن توجه داشت این است که شی response.json()‎ فراخوانی می‌شود. در واقع، شیئی که با استفاده از تابع dumps(). بازگردانده شده، فراخوانی نمی‌شود. از اینجا به بعد می‌توان از این داده‌ها برای آنکه داده‌ها به سادگی به مجموعه داده الحاق (Append) شوند، با استفاده از هر روشی که کاربر بخواهد، استفاده کرد. در ادامه و در بخش بعدی، Dark Sky API مورد بررسی قرار خواهد گرفت.

روش کار با Dark Sky API و دریافت داده‌ها با احراز هویت

پیش از شروع کار با Dark Sky API، کاربر باید با مفهوم کلید رمز API آشنا باشد. کلیدهایی که به کار امکان احراز هویت بدون نیاز به فراهم کردن نام کاربری و گذرواژه می‌دهند را کلید رمز API می‌گویند. با توجه به آنچه گفته شد، باید با کلیدها به عنوان یک چیز رمزی و خصوصی برخورد کرد و آن را عمومی نکرد.  برای دریافت کلید رمزی Dark Sky باید یک حساب کاربری در وب‌سایت آن [+] ثبت کرد. پس از آنکه کاربر این کار را انجام داد، باید در صفحه [+] کلید API را دریافت کرد. کاربر باید این کلید رو جایی به صورت خصوصی ذخیره و نگه‌داری کند.

آشنایی بیشتر با Dark Sky API

Dark Sky منبع کاملی برای داده‌های موجود برای این API است. برای دسترسی به این موارد، باید مستندات آن را مطالعه کرد. دو نوع فراخوانی در این API وجود دارد. این فراخوانی‌ها عبارتند از:

  • درخواست پیش‌بینی (Forecast request)
  • درخواست ماشین زمان (Time Machine Request)

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

https://api.darksky.net/forecast/[key]/[latitude],[longitude]

این یعنی نیاز به سه چیز است.

  • کلید API کاربر
  • عرض جغرافیایی کاربر
  • طول جغرافیایی کاربر

کاربر برای آنکه بتواند به راحتی طول و عرض جغرافیایی محل مورد نظر خود را استخراج کند، می‌تواند آدرس مورد نظر را در نقشه گوگل قرار دهد. برای مثال، جستجو برای «برج سی‌ان» (Toronto’s CN Tower) انجام می‌شود. URL که توسط نقشه گوگل ارائه می‌شود، حاوی مختصات مورد نیاز کاربر است. URL ارائه شده برای مثال بیان شده در این بخش، در زیر ارائه شده است.

https://www.google.com/maps/place/CN+Tower/@43.6425701,-79.3892455,17z/

پس از علامت @، طول جغرافیایی (43.6425701) و بعد از آن، عرض جغرافیایی (79.3892455-) ارائه شده است. اکنون، کد لازم برای حل مسئله بیان شده در ادامه این بخش، در ادامه ارائه شده است. در اینجا، از f-strings برای ساده‌تر کردن کدنویسی انجام شده است. دستور دریافت عمومی (Generic Request)، داده‌هایی بیش از آنچه کاربر نیاز دارد را در اختیار او قرار می‌دهد. نظر به اینکه کاربر به این داده‌ها نیاز ندارد، هرس کردن با استفاده از بلوک اختصاصی Dark Sky انجام می‌شود. این کار، تأخیر روی درخواست را کاهش می‌دهد. در این راستا، فقط از بلوک currently استفاده می‌شود، بنابراین سایر موارد در نظر گرفته نمی‌شوند.

1secret_key = 'ENTER YOUR KEY HERE'
2longitude = -79.3892455
3latitude = 43.6425701
4exclude = 'minutely, hourly, daily, alerts, flags'
5
6url = f'https://api.darksky.net/forecast/{secret_key}/{latitude},{longitude}?exclude={exclude}'
7
8response = requests.get(url)
9dictionary = json.dumps(response.json(), sort_keys = True, indent = 4)
10print(dictionary)

خروجی قطعه کد بالا، به صورت زیر است.

{
    "currently": {
        "apparentTemperature": 32.25,
        "cloudCover": 1,
        "dewPoint": 36.38,
        "humidity": 0.95,
        "icon": "rain",
        "nearestStormDistance": 0,
        "ozone": 379.2,
        "precipIntensity": 0.076,
        "precipIntensityError": 0.03,
        "precipProbability": 1,
        "precipType": "rain",
        "pressure": 998.6,
        "summary": "Light Rain",
        "temperature": 37.76,
        "time": 1583257909,
        "uvIndex": 2,
        "visibility": 0.245,
        "windBearing": 71,
        "windGust": 12.67,
        "windSpeed": 7.32
    },
    "latitude": 43.6425701,
    "longitude": -79.3892455,
    "offset": -5,
    "timezone": "America/Toronto"
}

پیش از این، بیان شد که فرض بر آن است که کاربر تمایل به شرایط آب و هوای کنونی (به طور خاص، خلاصه، درجه حرارت و وزش باد) دارد. با بررسی ساختار بالا، می‌توان مشاهده کرد که می‌توان با حفظ خوانایی، این داده‌ها را با دسترسی به جفت‌های کلید مقدار برای آن عناصر، دریافت کرد. Dark Sky API به کاربر امکان تنظیم واحدها را نیز می‌دهد. اکنون، مشخص نیست که داده‌ها در چه واحدهایی استخراج می‌شوند. بنابراین، نیاز به صریح‌تر کردن کد است. با توجه به آنکه داده‌ها برای منطقه کانادایی دریافت می‌شوند، ناحیه محلی آن‌ها تعیین می‌شود. مستندات Dark Sky API می‌گوید که برای این کار، واحدها روی چه تنظیم شوند؛ در این مثال، به صورت units=si است.

1secret_key = 'ENTER YOUR KEY HERE'
2longitude = -79.3892455
3latitude = 43.6425701
4exclude = 'minutely, hourly, daily, alerts, flags'
5
6url = f'https://api.darksky.net/forecast/{secret_key}/{latitude},{longitude}?units=ca&exclude={exclude}'
7
8response = requests.get(url)
9response_json = response.json()
10
11current_summary = response_json['currently']['summary']
12current_temperature = response_json['currently']['temperature']
13current_wind_speed = response_json['currently']['windSpeed']
14
15print(f'The current temperature in Toronto, Ontario is {current_temperature} degrees Celsius and the wind speed is {current_wind_speed} km/h.')
16print(f'The current conditions are: {current_summary}.')

خروجی قطعه کد بالا به صورت زیر است.

The current temperature in Toronto, Ontario is 3.22 degrees Celsius and the wind speed is 11.75 km/h. 
The current conditions are: Light Rain.

در این قسمت، چگونگی دریافت داده‌ها با استفاده از API و احراز هویت، آموزش داده شد.

افزودن داده به چارچوب داده پانداس

برای این مثال، از API مالی Quandl استفاده شده است. به طور کلی، از API رایگان برای بورس فرانکفورت (Frankfurt’s Stock Exchange) استفاده می‌شود. کار با اکتشاف داده‌ها آغاز می‌شود. دریافت داده‌ها با دستورالعمل موجود برای تولید URL روی وب‌سایت و چاپ کردن داده‌ها با استفاده از تابع json.dumps()‎ انجام می‌شود که در بالا تشریح شده است. در این راستا، نیاز به وارد کردن کتابخانه‌هایی که در مثال‌های پیشین نیز بیان شد، به علاوه کتابخانه پایتون «پانداس» (Pandas) است.

1import pandas as pd
2import requests
3import json
4
5response = requests.get('https://www.quandl.com/api/v3/datasets/FSE/BDT_X')
6dictionary = json.dumps(response.json(), sort_keys = True, indent = 4)
7print(dictionary)

خروجی قطعه کد بالا، به صورت زیر است.

{
    "dataset": {
        "collapse": null,
        "column_index": null,
        "column_names": [
            "Date",
            "Open",
            "High",
            "Low",
            "Close",
            "Change",
            "Traded Volume",
            "Turnover",
            "Last Price of the Day",
            "Daily Traded Units",
            "Daily Turnover"
        ],
        "data": [
            [
                "2020-02-28",
                41.8,
                43.45,
                41.8,
                42.45,
                null,
                22878.0,
                973693.95,
                null,
                null,
                null
            ],
            [
                "2020-02-27",
                43.0,
                45.05,
                43.0,
                44.2,
                null,
                20369.0,
                894841.4,
                null,
                null,
                null
            ],
            [
                "2020-02-26",
                44.0,
                45.1,
                42.5,
                44.25,
                null,
                15533.0,
                683974.6,
                null,
                null,
                null
            ],
            ...

البته در واقع، داده‌ها بیش از این ادامه خواهند داشت و در بالا، تنها بخش کوچکی از خروجی ارائه شده است. بر این اساس می‌توان موارد زیر را مشاهده کرد:

  • نام ستون‌ها در [‘dataset’][‘column_names’] وجود دارد.
  • داده‌ها در [‘dataset’][‘data’] وجود دارند.

در ادامه، یک چارچوب داده با داشتن این دانش ساخته می‌شود.

1import pandas as pd
2import requests
3import json
4
5response = requests.get('https://www.quandl.com/api/v3/datasets/FSE/BDT_X')
6response_json = response.json()
7df = pd.DataFrame(response_json['dataset']['data'], columns = response_json['dataset']['column_names'])
8print(df)

خروجی قطعه کد بالا به صورت زیر است.

            Date   Open   High    Low  Close  Change  Traded Volume  \ ....
0     2020-02-28  41.80  43.45  41.80  42.45     NaN        22878.0   
1     2020-02-27  43.00  45.05  43.00  44.20     NaN        20369.0   
2     2020-02-26  44.00  45.10  42.50  44.25     NaN        15533.0   
3     2020-02-25  46.50  46.85  43.85  44.05     NaN        12435.0   
4     2020-02-24  47.65  47.65  45.10  45.95     NaN        19602.0   
...          ...    ...    ...    ...    ...     ...            ...   
5167  2000-01-07    NaN    NaN    NaN  82.30     NaN            0.0   
5168  2000-01-06    NaN    NaN    NaN  82.30     NaN            0.0   
5169  2000-01-05    NaN    NaN    NaN  82.30     NaN            0.0   
5170  2000-01-04    NaN    NaN    NaN  82.30     NaN            0.0   
5171  2000-01-03    NaN    NaN    NaN  82.30     NaN            0.0

جمع‌بندی

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

اگر نوشته بالا برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۱ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
Towards Data Science
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *