Краще вискоблювання веб-сторінок на Python за допомогою селену, прекрасного супу та панд

Веб-вишкрібання

Використовуючи мову програмування Python, можна швидко і ефективно «зішкребти» дані з Інтернету.

Веб-скрапінг визначається як:

інструмент для перетворення неструктурованих даних в Інтернеті в машиночитані структуровані дані, готові до аналізу. (джерело)

Веб-скрапінг є цінним інструментом у наборі навичок вченого з даних.

Тепер, що зішкребти?

Загальнодоступні дані

Веб-сайт KanView підтримує “Прозорість в уряді”. Це також гасло сайту. На сайті представлені дані про заробітну плату штату Канзас. І це чудово!

Проте, як і багато урядових веб-сайтів, він заховає дані у детальні посилання та таблиці. Часто для цього потрібна "найкраща навігаційна навігація", щоб знайти конкретні дані, які ви шукаєте. Я хотів використати публічні дані, надані університетам штату Канзас, у дослідницькому проекті. Для початку мені потрібно було зішкребти дані за допомогою Python та зберегти їх як JSON.

Посилання на JavaScript збільшують складність

Веб-скрапінг за допомогою Python часто вимагає не більше, ніж використання модуля Beautiful Soup для досягнення мети. Beautiful Soup - це популярна бібліотека Python, яка полегшує реалізацію веб-скрапінгу шляхом обходу DOM (об’єктної моделі документа).

Однак веб-сайт KanView використовує посилання на JavaScript. Тому приклади використання Python та Beautiful Soup не спрацюють без додаткових доповнень.

На допомогу селен

Пакет Selenium використовується для автоматизації взаємодії веб-браузера з Python. За допомогою Selenium можливо програмування сценарію Python для автоматизації веб-браузера. Згодом ці настирливі посилання на JavaScript більше не є проблемою.

from selenium import webdriver from selenium.webdriver.common.keys import Keys from bs4 import BeautifulSoup import re import pandas as pd import os

Тепер Selenium розпочне сеанс браузера. Щоб Selenium працював, він повинен отримати доступ до драйвера браузера. За замовчуванням він буде виглядати в тому ж каталозі, що і сценарій Python. Посилання на драйвери Chrome, Firefox, Edge та Safari доступні тут. У наведеному нижче прикладі коду використовується Firefox:

#launch url url = "//kanview.ks.gov/PayRates/PayRates_Agency.aspx" # create a new Firefox session driver = webdriver.Firefox() driver.implicitly_wait(30) driver.get(url) python_button = driver.find_element_by_id('MainContent_uxLevel1_Agencies_uxAgencyBtn_33') #FHSU python_button.click() #click fhsu link

python_button.click()Вище говорить Селен натиснути на посилання JavaScript на цій сторінці. Потрапивши на сторінку з назвами робочих місць, Селен передає джерело сторінки Прекрасному супу.

Перехід до красивого супу

Beautiful Soup залишається найкращим способом пройти DOM і зішкребти дані. Після визначення порожнього списку та змінної лічильника, час попросити Beautiful Soup захопити всі посилання на сторінці, які відповідають регулярному виразу:

#Selenium hands the page source to Beautiful Soup soup_level1=BeautifulSoup(driver.page_source, 'lxml') datalist = [] #empty list x = 0 #counter for link in soup_level1.find_all('a', id=re.compile("^MainContent_uxLevel2_JobTitles_uxJobTitleBtn_")): ##code to execute in for loop goes here

З наведеного вище прикладу видно, що Beautiful Soup отримає посилання на JavaScript для кожної посади в державному агентстві. Тепер у блоці коду циклу for / in Selenium натискає кожне посилання JavaScript. Потім Beautiful Soup отримає таблицю з кожної сторінки.

#Beautiful Soup grabs all Job Title links for link in soup_level1.find_all('a', id=re.compile("^MainContent_uxLevel2_JobTitles_uxJobTitleBtn_")): #Selenium visits each Job Title page python_button = driver.find_element_by_id('MainContent_uxLevel2_JobTitles_uxJobTitleBtn_' + str(x)) python_button.click() #click link #Selenium hands of the source of the specific job page to Beautiful Soup soup_level2=BeautifulSoup(driver.page_source, 'lxml') #Beautiful Soup grabs the HTML table on the page table = soup_level2.find_all('table')[0] #Giving the HTML table to pandas to put in a dataframe object df = pd.read_html(str(table),header=0) #Store the dataframe in a list datalist.append(df[0]) #Ask Selenium to click the back button driver.execute_script("window.history.go(-1)") #increment the counter variable before starting the loop over x += 1

pandas: Бібліотека аналізу даних Python

Beautiful Soup передає знахідки пандам. Pandas використовує свою read_htmlфункцію для зчитування даних таблиці HTML у фрейм даних. Кадр даних додається до раніше визначеного порожнього списку.

Перед завершенням блоку коду циклу Selenium потрібно натиснути кнопку назад у браузері. Це означає, що наступне посилання в циклі буде доступним для натискання на сторінці списку вакансій.

Після завершення циклу for / in Selenium відвідав кожне посилання на назву посади. Beautiful Soup отримав таблицю з кожної сторінки. Pandas зберігає дані з кожної таблиці у фреймі даних. Кожен фрейм даних - це елемент у даталісті. Тепер окремі таблиці кадрів таблиці повинні об'єднатися в один великий кадр даних. Далі дані будуть перетворені у формат JSON за допомогою pandas.Dataframe.to_json:

#loop has completed #end the Selenium browser session driver.quit() #combine all pandas dataframes in the list into one big dataframe result = pd.concat([pd.DataFrame(datalist[i]) for i in range(len(datalist))],ignore_index=True) #convert the pandas dataframe to JSON json_records = result.to_json(orient='records')

Тепер Python створює файл даних JSON. Він готовий до використання!

#get current working directory path = os.getcwd() #open, write, and close the file f = open(path + "\\fhsu_payroll_data.json","w") #FHSU f.write(json_records) f.close()

Автоматизований процес є швидким

Описаний вище автоматизований процес вишкрібання веб-сторінок швидко завершується. Selenium відкриває вікно браузера, яке ви бачите як працює. Це дозволяє мені показати вам відеозйомку екрану про те, наскільки швидким є процес. Ви бачите, як швидко сценарій йде за посиланням, захоплює дані, повертається назад і клацає наступне посилання. Це робить отримання даних із сотень посилань питанням одноцифрових хвилин.

Повний код Python

Ось повний код Python. Я включив імпорт для таблиці. Для цього потрібен додатковий рядок коду, який використовуватиме таблицю для гарного друку даних у інтерфейсі командного рядка:

from selenium import webdriver from selenium.webdriver.common.keys import Keys from bs4 import BeautifulSoup import re import pandas as pd from tabulate import tabulate import os #launch url url = "//kanview.ks.gov/PayRates/PayRates_Agency.aspx" # create a new Firefox session driver = webdriver.Firefox() driver.implicitly_wait(30) driver.get(url) #After opening the url above, Selenium clicks the specific agency link python_button = driver.find_element_by_id('MainContent_uxLevel1_Agencies_uxAgencyBtn_33') #FHSU python_button.click() #click fhsu link #Selenium hands the page source to Beautiful Soup soup_level1=BeautifulSoup(driver.page_source, 'lxml') datalist = [] #empty list x = 0 #counter #Beautiful Soup finds all Job Title links on the agency page and the loop begins for link in soup_level1.find_all('a', id=re.compile("^MainContent_uxLevel2_JobTitles_uxJobTitleBtn_")): #Selenium visits each Job Title page python_button = driver.find_element_by_id('MainContent_uxLevel2_JobTitles_uxJobTitleBtn_' + str(x)) python_button.click() #click link #Selenium hands of the source of the specific job page to Beautiful Soup soup_level2=BeautifulSoup(driver.page_source, 'lxml') #Beautiful Soup grabs the HTML table on the page table = soup_level2.find_all('table')[0] #Giving the HTML table to pandas to put in a dataframe object df = pd.read_html(str(table),header=0) #Store the dataframe in a list datalist.append(df[0]) #Ask Selenium to click the back button driver.execute_script("window.history.go(-1)") #increment the counter variable before starting the loop over x += 1 #end loop block #loop has completed #end the Selenium browser session driver.quit() #combine all pandas dataframes in the list into one big dataframe result = pd.concat([pd.DataFrame(datalist[i]) for i in range(len(datalist))],ignore_index=True) #convert the pandas dataframe to JSON json_records = result.to_json(orient='records') #pretty print to CLI with tabulate #converts to an ascii table print(tabulate(result, headers=["Employee Name","Job Title","Overtime Pay","Total Gross Pay"],tablefmt='psql')) #get current working directory path = os.getcwd() #open, write, and close the file f = open(path + "\\fhsu_payroll_data.json","w") #FHSU f.write(json_records) f.close()

Висновок

Web scraping with Python and Beautiful Soup is an excellent tool to have within your skillset. Use web scraping when the data you need to work with is available to the public, but not necessarily conveniently available. When JavaScript provides or “hides” content, browser automation with Selenium will insure your code “sees” what you (as a user) should see. And finally, when you are scraping tables full of data, pandas is the Python data analysis library that will handle it all.

Reference:

The following article was a helpful reference for this project:

//pythonprogramminglanguage.com/web-scraping-with-pandas-and-beautifulsoup/

Reach out to me any time on LinkedIn or Twitter. And if you liked this article, give it a few claps. I will sincerely appreciate it.

//www.linkedin.com/in/davidagray/

Dave Gray (@yesdavidgray) | Twitter

The latest Tweets from Dave Gray (@yesdavidgray). Instructor @FHSUInformatics * Developer * Musician * Entrepreneur *…

twitter.com