آنچه در این مقاله میخوانید
آموزش 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
بهتر است قبل از شروع توسعه پروژه یک محیط مجازی (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