По-добро изстъргване на мрежа в 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, той трябва да има достъп до драйвера на браузъра. По подразбиране ще изглежда в същата директория като скрипта на 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 на страницата. След като пристигна на страницата със заглавия на длъжностите, Selenium предава източника на страницата на Beautiful Soup.

Преход към красива супа

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