اینترنت منبع بسیار غنی از اطلاعات و داده است. اگر بتوان با تکنیک های برنامه نویسی و علم داده حجم قابل توجهی از اطلاعات را جمع آوری نمود می توان از این داده ها استفاده بهتری نمود. در این مطلب قصد دارم به شما آموزش دهم چگونه می توان با استفاده از پایتون و کتابخانه های Beautiful Soup , Selenium و Pandas استفاده کنید تا بتوانید اطلاعات مورد نیاز خود را از وب جمع آوری کنید. به این نرم افزار خزنده وب یا web scraping یا web crawler می گویند.
بررسی اجمالی فرآیند
فرآیند خزنده وب را می توان به سه قسمت مختلف تقسیم بندی کرد.
- درک یک صفحه HTML برای شناسایی تگ های مورد نظر
- برای طراحی خزنده از کتابخانه های Beautiful Soup , Selenium و Pandas استفاده کنید.
- داده های بدست آمده از خزنده را تغییر بدهید تا به شکل و فرمت دلخواه دست پیدا کنید.
اولین مرحله شامل بررسی HTML یک صفحه وب است. برای طراحی یک خزنده وب نیاز است دانش حداقلی از HTML داشته باشید. زبان HTML شام تگ های مختلف است. تگ های تک بخشی یا دو بخشی. برای مثال برای نوشتن یک تکه متن از تگ زیر استافاده می شود.
<p>This is a paragraph</p>
با استفاده از این برچسب ها ، کتابخانه های خزنده وب می توانند اطلاعات را در تمام مراحل خزش به طور موثر هدف قرار دهند و تجزیه کنند. مثالهای زیر به توضیح جزئیات بیشتر روند فوق کمک می کند.
مثال ۱
اولین مثال مربوط به تهیه جدول و گرفتن اطلاعات از سایت Nepia.com که مشخص کند بیماری کرونا چه تاثیری در حمل و نقل داشته است.
کتابخانه های مورد نیاز را به محیط کار اضافه می کنیم.
import requests from bs4 import BeautifulSoup import pandas as pd url = "https://www.nepia.com/industry-news/coronavirus-outbreak- impact-on-shipping/" r = requests.get(url) soup = BeautifulSoup(r.content)
کد فوق محتوای HTML صفحه وب ما را در یک شی BeautifulSoup ذخیره می کند. با دستور زیر می توان کد های HTML آن را به چاپ کرد.
print(soup.prettify())
یک صفحه HTML شامل تعداد بسیار زیاد تگ است. برای آن که تگ مورد نظر که اطلاعات ما داخل آن است را پیدا کنیم F12 را می زنیم و از بخش Inspect تگ مورد را نظر را پیدا می کنیم. در این حالت بر روی هر بخش از صفحه مورد نظر کلیک کنیم تگ مربوط به آن قسمت مشخص می شود. اطلاعات مورد نظر ما در تگ <td> قرار دارد. از متد find_all برای پیدا کردن همه تگ های td کمک می گیریم.
print(soup.find_all('td'))
این روش تمام اطلاعات منطبق شده را بر می گرداند.
حال که می دانید چطور اطلاعات دلخواه را از یک صفحه وب استخراج کنید می توانید اطلاعات را به صورت دلخواه ذخیره کنید. قطعه کد زیر صفحه HTML را تجزیه می کند تا داده های مورد نیاز را در یک مجموعه داده pandas با چهار ستون کشور ، اطلاعات حزبی ، تاریخ و مشاوره مورد نیاز ما ذخیره کند.
a = [] df = pd.DataFrame(columns = ['Country', 'informing Party', 'Date', 'Summary of advice']) for link in soup.find_all('td'): a.append(link.get_text()) if len(a) == 4: df_length = len(df) df.loc[df_length] = a a = []
این کد از طریق هر عنصر در لیست تولید شده توسط find_all بررسی می شود و متن مربوط به آن عنصر را با استفاده از روش get_text بدست می آورد. دستور if اطمینان حاصل می کند که داده های بازیابی شده به شکلی است که ما به آن نیاز داریم.
گرچه Beautiful Soup می تواند تمام اطلاعات مورد نیاز ما را در این مورد بدست آورد ، اما نمی تواند به طور خودکار آن را به شکلی که دوست داریم ذخیره کند. به طور خاص ، این نمی تواند به ما بگوید که یک سطر در کجا پایان می یابد و ردیف بعدی شروع می شود روش find_all فقط لیستی از عناصر انتخاب شده را برمی گرداند. از این رو ، ما باید از درک خود از صفحه وب برای دستکاری نتایج استفاده کنیم.
مثال ۲
در این مثال ، ما می خواهیم هر کشور و محدودیت های سفر آن در دوران کرونا را از این لینک نشان دهیم. قسمت چالش برانگیز مساله این است که هیچ ساختار خوبی مانند جدول در مثال قبلی وجود ندارد.
یک بررسی سریع از صفحه به ما می گوید که کشورها با تگ <h3> برچسب گذاری شده اند و محدودیت های مربوط به آنها تحت برچسب <p> قرار دارند. بعلاوه ، یک کشور می تواند چندین پاراگراف داشته باشد ، مانند کشور آنگولا . هدف ما دستیابی به اطلاعات فوق در یک چارچوب داده با دو ستون کشور و محدودیت است.
مانند مثال قبلی اولین کار بدست آوردن تگ های HTML صفحه از طریق URL آن است. و آن را با به عنوان یک شی BeautifulSoup ذخیره کنید. با بررسی همه تگ های <h3> می بینید که فقط اسم کشور ها در این تگ وجود دارد بدون هیچ اطلاعات اضافی. اما بررسی تگ <p> نشان می دهد داده های دیگری هم در این تگ وجود دارد. پس باید دنبال روشی باشیم که فقط اطلاعات مربوط به محدودیت های کشور های مختلف را جدا کند. کد زیر این کار را انجام می دهد.
df = pd.DataFrame(columns =['Country', 'Restriction']) country = [] restriction = [] flag = 0 for link in soup2.find_all("h3"): if flag == 0: country.append(link.get_text()) next_sib = link.find_next_sibling(['p', 'h3']) print(next_sib.get_text()) text = [] # loop to go through all paragraphs that come after a h3 tag while next_sib.name != 'h3': text.append(next_sib.get_text()) next_sib = next_sib.find_next_sibling(['p','h3']) if next_sib is None : flag = 1 break restriction.append(' '.join(text)) else: break df['Country'] = country df['Restriction'] = restriction
قطعه کد فوق از روشی به نام find_next_sibling استفاده می کند که لیستی از برچسب های ارائه شده در پارامتر را بررسی می کند و مطابق تگ اول را برمی گرداند. در مثال بالا ، ابتدا همه برچسب های <h3> را پیدا می کنیم و سپس می توانیم برچسب<h3> یا <p> بعدی را با استفاده از find_next_sibling بدست آوریم. اگر تگ بررسی شده یک برچسب <p> باشد ، ما متن را ذخیره می کنیم ، اما در غیر این صورت ، کاری نمی کنیم.
مثال ۳
مثال اخر مربوط به دستورات ایمنی مربوط به کرونا در هر ایالت امریکاست. اطلاعات مورد نظر از این سایت جمع آوری می شود.
وب سایت مورد نظر دارای یک منوی کرکره ای است که در آن کاربر می تواند وضعیت مورد علاقه خود را مشخص کند. این وب سایت به گونه ای طراحی شده است که وقتی کاربر این مقدار را تغییر می دهد ، URL و HTML اصلی صفحه تغییر می کند. دو روش معمول برای خزنده وب سایت با طرح پویا مانند این وجود دارد:
- مشاهده کنید که URL هنگام انتخاب حالت های مختلف چگونه تغییر می کند و سپس درخواست های جداگانه را برای خزیدن وب به هر یک از این URL ها ارسال کنید.
- از یک کتابخانه دیگر به نام Selenium استفاده کنید که تعامل کاربر با مروگر خود را به صورت خودکار بررسی می کند. با استفاده از این روش می توانیم یک حالت را به صورت برنامه نویسی وارد منوی کرکره ای کنیم و صفحه HTML مرتبط را به عنوان یک شی Beautiful BeautifulSoup بدست آوریم.
برای کار با Selenium نیاز است مرورگر و درایور آن روی سیستم نصب باشد. درایور اجازه می دهد تا کد ما در یک پنجره مرورگر ایجاد و آن را کنترل کند. ما در این مثال از مرورگر کروم استفاده کرده ایم. درایور گوگل کروم را از اینجا می توانید دانلود کنید.
from selenium import webdriver import time drv_path = "/Users/dn/Desktop/chromedriver_win32/chromedriver.exe" driver = webdriver.Chrome(drv_path) # full path of browser driver url = 'https://covid19.healthdata.org/projections' # opening the url driver.get(url) time.sleep(5)
قطعه فوق ، اولین بخش از کد نهایی ما ، به سادگی صفحه وب مورد نظر را در یک پنجره مرورگر باز می کند. Time.sleep برای اطمینان از باز شدن ایمن صفحه قبل از اقدام بیشتر است ، زیرا بین ظاهر گرافیکی و کد فاصله وجود دارد. این کار به شما کمک می کند تا از بروز خطا جلوگیری شود.
به منظور خودکار کردن ورودی حالت های مختلف در منوی کرکره ای ، باید عنصر HTML مربوطه را پیدا کرده و هر حالت را به عنوان ورودی ارسال کنیم. روش های مختلفی برای تعیین مکان عناصر با استفاده از Selenium وجود دارد ، اما برای این مثال ، من روی روش find_element_by_XPath تمرکز می کنم.
در این روش باید xpath منوی کرکره ای را پیدا کنید. برای این کار بر روی منوی مورد نظر کلیک راست کرده و کپی XPath را انتخاب کنید. اطلاعات بدست آمده را در کد قرار دهید. چیزی شبیه به کد زیر:
dropdown = driver.find_element_by_xpath('//*[@id="rc_select_0"]')
برای ارسال مقدار مختلف به این منوی کرکره ای ، از send_keys استفاده کنید:
dropdown.send_keys('California') time.sleep(5) dropdown.send_keys(Keys.ENTER)
حال باید مانند مثال های قبل تگ های مورد نظر را شناسایی کنیم. با کمی بررسی کدهای HTML مشخص می شود اطلاعات در تگ <span> و در کلاس class=”_30-NvbQKNSCT3T454z5_47″ قرار دارد.
from selenium.webdriver.common.keys import Keys from selenium.common.exceptions import StaleElementReferenceException a = [] df = pd.DataFrame(columns = ['State','stay_at_home','educational_facilities_closed', 'non_essential_services_closed']) # output dataframe dd_xpath = '//*[@id="rc_select_0"]' for state in states['State'].unique(): # finding dropdown dropdown = driver.find_element_by_xpath(dd_xpath) time.sleep(5) a.append(state) try: dropdown.send_keys(state) time.sleep(5) except StaleElementReferenceException as Exception: print('Trying to find element again') dropdown = driver.find_element_by_xpath(dd_xpath) time.sleep(5) dropdown.send_keys(state) time.sleep(5) try: dropdown.send_keys(Keys.ENTER) time.sleep(5) except StaleElementReferenceException as Exception: print('Trying to find element again') dropdown = driver.find_element_by_xpath(dd_xpath) time.sleep(5) dropdown.send_keys(Keys.ENTER) time.sleep(5) # storing html page as BeautifulSoup object soup_level1 = BeautifulSoup(driver.page_source) print(state) div_class = "_30-NvbQKNSCT3T454z5_47" span_class = "ant-statistic-content-value" for link in soup_level1.find_all('div',{'class': div_class}): a.append(link.find('span',{"class": span_class}).get_text()) print(link.find('span',{"class": span_class}).get_text()) if len(a) == 4: df_length = len(df) df.loc[df_length] = a # appending row to dataframe a = [] break
نتیجه
اگر در زمینه خزنده وب تازه کار هستید ، مثال های بالا می توانند به عنوان یک نقطه شروع برای طراحی یک خزنده وب باشد. همه صفحات وب متفاوت هستند ، بنابراین طبیعتاً کد های فوق باید برای صفحات دیگر اصلاح شوند ، اما روند کلی آن باید یکسان باشد.
علاوه بر این ، کتابخانه های خزنده قدرتمند دیگری در پایتون وجود دارد. به عنوان مثال ، Scrapy ابزاری فوق العاده قدرتمند برای خزش در مقیاس بزرگ است. برای مبتدیان ، بهتر است ابتدا با مواردی که در اینجا بحث شده است شروع کنید و سپس بعداً در صورت لزوم ، از Scrapy استفاده کنید.
Hello. And Bye.
سلام خسته نباشید اطلاعات واقعا خوب و تخصصی خوبی بود استفاده کردم کاربردی بود دمتون گرم.