تغییرات اخیر

در اینجا اطلاعیه‌ها، نسخه‌ها و تغییرات جدید لیارا فهرست می‌شوند.

آموزش Web Scraping با Selenium


۶ اسفند ۱۳۹۹

Selenium ابزاری است که به شما در اجرای تست‌‌های خودکار برنامه‌‌های وب کمک می‌کند. اگرچه هدف اصلی این مقاله از لیارا، استفاده از Selenium برای Web Scraping با استفاده از اسکریپت پایتون است اما شما می‌توانید در زمینه‌های مختلفی از مزیت‌های این ابزار بهره‌مند شوید.

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

هدف برنامه‌ نهایی ما، استخراج نوسان‌های نرخ دلار از وبسایت investing.com است.

همین الان، بدون هیچ‌گونه پیچیدگی، هاست Python خود را در کمتر از ۳۰ ثانیه راه‌اندازی کنید.
✅ استقرار سریع و آسان ✅ پشتیبانی از فریم‌ورک‌های مختلف ✅ عملکرد پایدار
خرید هاست Python

آنچه در ادامه خواهید خواند:

  • تجزیه و تحلیل URL
  • Web Scraping با Selenium
  • مدیریت Exception ها در Selenium
  • سوالات متداول
  • جمع بندی

تجزیه و تحلیل URL

در این بخش، URL وب‌سایت هدف را تجزیه و تحلیل خواهیم کرد. در این آدرس از وب‌سایت investing.com نوسان‌های نرخ دلار به‌نسبت یورو نمایش داده می‌شود. همچنین در این صفحه می‌توانید تاریخ معینی را تعیین کنید و نوسان‌های این دو ارز را در بازه‌ خاصی از زمان مشاهده کنید.

نکته: برای مشاهده‌ی سایر ارز‌ها به‌نسبت نوسان‌های دلار می‌توانید مقدار eur را با ارز دلخواه خود در URL فوق جایگزین کنید.

آموزش web scraping با selenium

Web Scraping با Selenium

بهتر است قبل از شروع توسعه‌ پروژه یک محیط مجازی (Virtual environment) ایجاد کنید که در مقاله‌ آموزش نصب و استفاده از Virtual environment در Python عمیق‌تر به این موضوع پرداخته‌ایم بنابراین ابتدا آن را مطالعه کنید و در مرحله بعد به ادامه این مقاله بپردازید.

پس از ساخت محیط مجازی و active کردن آن، وابستگی‌های پروژه را با اجرای دستور‌های زیر نصب کنید.

pip install selenium
pip install pandas
pip install lxml

حال یک فایل با نام main.py در محیط مجازی ایجاد کرده، بنابراین باید به توسعه آن بپردازید.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas

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

  • لیستی از کدهای ارزها
  • تاریخ شروع بازه‌ زمانی معین
  • تاریخ پایان بازه‌ زمانی معین
  • یک مقدار Boolean برای زمانی که بخواهید خروجی برنامه را در یک فایل .csv دریافت کنید.

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

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []

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

سپس بایستی پنجره‌ باز شده‌ مرورگر را Maximize کنید. البته نتیجه‌ این کار تنها با فعال بودن گزینه‌ option.headless = False قابل مشاهده است.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:

        # Opening the connection and grabbing the page
        chrome_driver_path = ''
        my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
        option = Options()
        option.headless = False
        option.executable_path = chrome_driver_path
        driver = webdriver.Chrome(options=option)
        driver.get(my_url)
        driver.maximize_window()


در کدهای بالا بایستی مقدار متغیر chrome_driver_path را تعیین کنید اما پیش از آن بایستی ChromeDriver را دانلود کرده باشید. به‌عنوان مثال ChromeDriver ما در مسیر زیر قرار دارد.

C:/liara/selenium-scrapper/pys/chromedriver.exe

بنابراین مقدار متغیر chrome_driver_path را به شکل زیر تعیین کنید.

chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'

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

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

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:

        # Opening the connection and grabbing the page
        chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
        my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
        option = Options()
        option.headless = False
        option.executable_path = chrome_driver_path
        driver = webdriver.Chrome(options=option)
        driver.get(my_url)
        driver.maximize_window()
        # Clicking on the date button
        date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
        date_button.click()

اکنون باید فیلدهای مربوط به Start Date را پر کنید.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:

        # Opening the connection and grabbing the page
        chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
        my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
        option = Options()
        option.headless = False
        option.executable_path = chrome_driver_path
        driver = webdriver.Chrome(options=option)
        driver.get(my_url)
        driver.maximize_window()
        # Clicking on the date button
        date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
        date_button.click()
        # Sending the start date
        start_bar = driver.find_element_by_id('startDate')
        start_bar.clear()
        start_bar.send_keys(start)

با استفاده از clear تمام داده‌های پیش‌فرض این فیلد حذف شده و با استفاده از send_keys، داده‌های جدید را در این فیلد قرار دهید. همچنین این روند را نیز بایستی برای End Date تکرار کنید.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:

        # Opening the connection and grabbing the page
        chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
        my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
        option = Options()
        option.headless = False
        option.executable_path = chrome_driver_path
        driver = webdriver.Chrome(options=option)
        driver.get(my_url)
        driver.maximize_window()
        # Clicking on the date button
        date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
        date_button.click()
        # Sending the start date
        start_bar = driver.find_element_by_id('startDate')
        start_bar.clear()
        start_bar.send_keys(start)
        # Sending the end date
        end_bar = driver.find_element_by_id('endDate')
        end_bar.clear()
        end_bar.send_keys(end)

سپس بایستی بر روی دکمه‌ی Apply کلیک کنید تا فیلترها اعمال شوند. همچنین از sleep استفاده کنید تا برنامه‌ برای چند ثانیه متوقف شده و صفحه‌ جدید کاملا بارگیری شود.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:

        # Opening the connection and grabbing the page
        chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
        my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
        option = Options()
        option.headless = False
        option.executable_path = chrome_driver_path
        driver = webdriver.Chrome(options=option)
        driver.get(my_url)
        driver.maximize_window()
        # Clicking on the date button
        date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
        date_button.click()
        # Sending the start date
        start_bar = driver.find_element_by_id('startDate')
        start_bar.clear()
        start_bar.send_keys(start)
        # Sending the end date
        end_bar = driver.find_element_by_id('endDate')
        end_bar.clear()
        end_bar.send_keys(end)
        # Clicking on the apply button
        apply_button = driver.find_element_by_id('applyBtn')
        apply_button.click()
        sleep(5)

اگر option.headless را برابر با False قرار داده باشید می‌توانید تمام فرایند اجرای برنامه را مشاهده کنید. حال زمان آن است که از فانکشن pandas.read_html برای انتخاب کردن جدول مورد نظرتان در صفحه‌ی وب استفاده کنید. این فانکشن source code صفحه را دریافت می‌کند و پس از آن می‌توانید از ChromeDriver فعلی خارج شوید.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:
        # Opening the connection and grabbing the page
        chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
        my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
        option = Options()
        option.headless = False
        option.executable_path = chrome_driver_path
        driver = webdriver.Chrome(options=option)
        driver.get(my_url)
        driver.maximize_window()
        # Clicking on the date button
        date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
        date_button.click()
        # Sending the start date
        start_bar = driver.find_element_by_id('startDate')
        start_bar.clear()
        start_bar.send_keys(start)
        # Sending the end date
        end_bar = driver.find_element_by_id('endDate')
        end_bar.clear()
        end_bar.send_keys(end)
        # Clicking on the apply button
        apply_button = driver.find_element_by_id('applyBtn')
        apply_button.click()
        sleep(5)
        # Getting the tables on the page and quiting
        dataframes = pandas.read_html(driver.page_source)

        driver.quit()
        print(f'{currency} scraped.')

بهترین هاست پایتون ایران و خارج چیست؟
هاست پایتون ایران و خارج

مدیریت Exceptionها در Selenium

فرایند جمع‌آوری داده‌ها در بخش قبل تمام شد اما بایستی Exception های احتمالی را درنظر بگیرید. به‌همین منظور از try استفاده کنید تا اگر برنامه‌ با مشکلی روبرو شد قادر باشید آن را مدیریت کنید. سناریو به‌صورت زیر است.

  • ChromeDriver به‌منظور استفاده‌ی بهینه از memory، بسته شود.
  • در زمان ایجاد خطا یک پیام در Console چاپ شود.
  • پس از آن برنامه برای ده ثانیه متوقف شود.
  • برنامه مجددا اجرا شود.

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

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:
        try:
            # Opening the connection and grabbing the page
            chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
            my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
            option = Options()
            option.headless = False
            option.executable_path = chrome_driver_path
            driver = webdriver.Chrome(options=option)
            driver.get(my_url)
            driver.maximize_window()
            # Clicking on the date button
            date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
            date_button.click()
            # Sending the start date
            start_bar = driver.find_element_by_id('startDate')
            start_bar.clear()
            start_bar.send_keys(start)
            # Sending the end date
            end_bar = driver.find_element_by_id('endDate')
            end_bar.clear()
            end_bar.send_keys(end)
            # Clicking on the apply button
            apply_button = driver.find_element_by_id('applyBtn')
            apply_button.click()
            sleep(5)
            # Getting the tables on the page and quiting
            dataframes = pandas.read_html(driver.page_source)

            driver.quit()
            print(f'{currency} scraped.')

        except:
            driver.quit()
            print(f'Failed to scrape {currency}. Trying again in 10 seconds.')
            sleep(10)
            continue

تا به این قسمت تمام صفحه‌ وب را در متغیری با نام dataframes ذخیره کرده‌اید. حال بایستی جدول مورد نظر را از بقیه‌ کدهای موجود در صفحه، جدا کنید.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:
        try:
            # Opening the connection and grabbing the page
            chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
            my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
            option = Options()
            option.headless = False
            option.executable_path = chrome_driver_path
            driver = webdriver.Chrome(options=option)
            driver.get(my_url)
            driver.maximize_window()
            # Clicking on the date button
            date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
            date_button.click()
            # Sending the start date
            start_bar = driver.find_element_by_id('startDate')
            start_bar.clear()
            start_bar.send_keys(start)
            # Sending the end date
            end_bar = driver.find_element_by_id('endDate')
            end_bar.clear()
            end_bar.send_keys(end)
            # Clicking on the apply button
            apply_button = driver.find_element_by_id('applyBtn')
            apply_button.click()
            sleep(5)
            # Getting the tables on the page and quiting
            dataframes = pandas.read_html(driver.page_source)

            driver.quit()
            print(f'{currency} scraped.')

        except:
            driver.quit()
            print(f'Failed to scrape {currency}. Trying again in 10 seconds.')
            sleep(10)
            continue

    # Selecting the correct table
    for dataframe in dataframes:
        if dataframe.columns.tolist() == ['Date', 'Price', 'Open', 'High', 'Low', 'Change %']:
            frames.append(dataframe)

اکنون اگر مقدار export_csv برابر با True باشد، بایستی داده‌های خروجی را با استفاده از dataframe.to_csv در یک فایل .csv ذخیره کنید.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:
        try:
            # Opening the connection and grabbing the page
            chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
            my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
            option = Options()
            option.headless = False
            option.executable_path = chrome_driver_path
            driver = webdriver.Chrome(options=option)
            driver.get(my_url)
            driver.maximize_window()
            # Clicking on the date button
            date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
            date_button.click()
            # Sending the start date
            start_bar = driver.find_element_by_id('startDate')
            start_bar.clear()
            start_bar.send_keys(start)
            # Sending the end date
            end_bar = driver.find_element_by_id('endDate')
            end_bar.clear()
            end_bar.send_keys(end)
            # Clicking on the apply button
            apply_button = driver.find_element_by_id('applyBtn')
            apply_button.click()
            sleep(5)
            # Getting the tables on the page and quiting
            dataframes = pandas.read_html(driver.page_source)

            driver.quit()
            print(f'{currency} scraped.')

        except:
            driver.quit()
            print(f'Failed to scrape {currency}. Trying again in 10 seconds.')
            sleep(10)
            continue

    # Selecting the correct table
    for dataframe in dataframes:
        if dataframe.columns.tolist() == ['Date', 'Price', 'Open', 'High', 'Low', 'Change %']:
            frames.append(dataframe)
            # Exporting the .csv file
            if export_csv:
                dataframe.to_csv('currency.csv', index=False)
                print(f'{currency}.csv exported.')

    return frames

حال برای اجرای برنامه می‌توانید این فانکشن را فراخوانی کرده و فایل main.py را با دستور python main.py اجرا کنید.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import pandas


def get_currencies(currencies, start, end, export_csv=True):
    frames = []
    for currency in currencies:
        try:
            # Opening the connection and grabbing the page
            chrome_driver_path = 'C:/liara/selenium-scrapper/pys/chromedriver.exe'
            my_url = f'https://investing.com/currencies/usd-{currency.lower()}-historical-data'
            option = Options()
            option.headless = False
            option.executable_path = chrome_driver_path
            driver = webdriver.Chrome(options=option)
            driver.get(my_url)
            driver.maximize_window()
            # Clicking on the date button
            date_button = driver.find_element_by_id('flatDatePickerCanvasHol')
            date_button.click()
            # Sending the start date
            start_bar = driver.find_element_by_id('startDate')
            start_bar.clear()
            start_bar.send_keys(start)
            # Sending the end date
            end_bar = driver.find_element_by_id('endDate')
            end_bar.clear()
            end_bar.send_keys(end)
            # Clicking on the apply button
            apply_button = driver.find_element_by_id('applyBtn')
            apply_button.click()
            sleep(5)
            # Getting the tables on the page and quiting
            dataframes = pandas.read_html(driver.page_source)

            driver.quit()
            print(f'{currency} scraped.')

        except:
            driver.quit()
            print(f'Failed to scrape {currency}. Trying again in 10 seconds.')
            sleep(10)
            continue

    # Selecting the correct table
    for dataframe in dataframes:
        if dataframe.columns.tolist() == ['Date', 'Price', 'Open', 'High', 'Low', 'Change %']:
            frames.append(dataframe)
            # Exporting the .csv file
            if export_csv:
                dataframe.to_csv('currency.csv', index=False)
                print(f'{currency}.csv exported.')

    return frames


print(get_currencies(['eur'], '01/13/2021', '02/13/2021'))

نحوه اتصال به سرور مجازی با استفاده از WebSSH در پایتون Python
WebSSH در پایتون Python

سوالات متداول

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

آیا استفاده از Selenium برای Web Scraping قانونی است؟

استفاده از Selenium برای استخراج داده‌ها بستگی به شرایط استفاده (Terms of Service) وب‌سایت مقصد دارد. پیشنهاد می‌شود قبل از استخراج داده‌ها، حتماً قوانین آن وب‌سایت را مطالعه کنید تا دچار مشکلات حقوقی نشوید.

تفاوت Selenium با BeautifulSoup یا Scrapy چیست؟

در حالی‌که ابزارهایی مثل BeautifulSoup فقط می‌توانند HTML اولیه را پردازش کنند، Selenium قابلیت تعامل با صفحات وب رندر شده توسط JavaScript را نیز دارد. بنابراین، برای صفحات داینامیک، Selenium انتخاب بهتری است.

برای اجرای این پروژه به چه مرورگری نیاز دارم؟

در این مقاله از Google Chrome و ChromeDriver استفاده شده است. اما می‌توانید با پیکربندی مناسب، از مرورگرهای دیگری مثل Firefox نیز بهره ببرید.

آیا می‌توان این پروژه را روی سرور بدون محیط گرافیکی اجرا کرد؟

بله. کافی است گزینه‌ی option.headless را برابر با True قرار دهید تا Chrome به‌صورت headless (بدون رابط گرافیکی) اجرا شود.

چرا باید از Virtual Environment استفاده کنیم؟

محیط مجازی کمک می‌کند وابستگی‌های هر پروژه را جداگانه و بدون تداخل با دیگر پروژه‌ها مدیریت کنید؛ مخصوصاً وقتی با ابزارهایی مثل Selenium کار می‌کنید که ممکن است نسخه‌های مختلفی از کتابخانه‌ها را نیاز داشته باشند.

جمع بندی

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

منبع: https://www.freecodecamp.org/news/how-to-code-a-scraping-bot-with-selenium-and-python

به اشتراک بگذارید

برچسب‌ها: