Bedre webskrabning i Python med selen, smuk suppe og pandaer

Webskrabning

Ved hjælp af Python-programmeringssproget er det muligt at "skrabe" data fra internettet på en hurtig og effektiv måde.

Webskrabning defineres som:

et værktøj til at omdanne de ustrukturerede data på nettet til maskinlæsbare, strukturerede data, som er klar til analyse. (kilde)

Webskrabning er et værdifuldt værktøj i dataforskernes færdigheder.

Hvad skal jeg skrabe nu?

Offentligt tilgængelige data

KanView-webstedet understøtter “Transparency in Government”. Det er også sloganet for webstedet. Webstedet giver løndata til staten Kansas. Og det er fantastisk!

Alligevel nedbryder det ligesom mange offentlige websteder dataene i uddybningslinks og tabeller. Dette kræver ofte ”bedste gætnavigation” for at finde de specifikke data, du leder efter. Jeg ønskede at bruge de offentlige data, der blev leveret til universiteterne i Kansas i et forskningsprojekt. At skrabe dataene med Python og gemme dem som JSON var hvad jeg havde brug for for at komme i gang.

JavaScript-links øger kompleksiteten

Webskrabning med Python kræver ofte ikke mere end brugen af ​​Beautiful Soup-modulet for at nå målet. Beautiful Soup er et populært Python-bibliotek, der gør webskrabning lettere ved at krydse DOM (dokumentobjektmodel).

KanView-webstedet bruger imidlertid JavaScript-links. Derfor fungerer eksempler, der bruger Python og Beautiful Soup, ikke uden ekstra tilføjelser.

Selen til undsætning

Selen-pakken bruges til at automatisere webbrowserinteraktion fra Python. Med Selen er det muligt at programmere et Python-script til automatisering af en webbrowser. Bagefter er disse irriterende JavaScript-links ikke længere et problem.

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

Selen vil nu starte en browsersession. For at Selen skal fungere, skal det have adgang til browserdriveren. Som standard ser det ud i samme bibliotek som Python-scriptet. Links til Chrome-, Firefox-, Edge- og Safari-drivere tilgængelige her. Eksempelkoden nedenfor bruger 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

Den python_button.click()ovenstående fortæller Selen at klikke på JavaScript-link på siden. Efter at have ankommet siden Jobtitler overleverer Selenium sidekilden til Beautiful Soup.

Overgang til smuk suppe

Smuk suppe er stadig den bedste måde at krydse DOM og skrabe dataene på. Efter at have defineret en tom liste og en tællervariabel, er det tid til at bede Beautiful Soup om at få fat i alle de links på siden, der matcher et regulært udtryk:

#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

Du kan se fra eksemplet ovenfor, at Beautiful Soup vil hente et JavaScript-link for hver jobtitel hos det statslige agentur. Nu i kodeblokken for for / in-sløjfen vil Selenium klikke på hvert JavaScript-link. Smuk suppe henter derefter tabellen fra hver side.

#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

pandaer: Python Data Analysis Library

Smuk suppe videregiver resultaterne til pandaer. Pandas bruger sin read_htmlfunktion til at læse HTML-tabeldataene i en dataramme. Dataframmen føjes til den tidligere definerede tomme liste.

Før kodeblokken for sløjfen er færdig, skal Selenium klikke på knappen Tilbage i browseren. Dette er så det næste link i sløjfen vil være tilgængeligt for at klikke på joblistesiden.

Når for / in-sløjfen er afsluttet, har Selenium besøgt hvert jobtitellink. Smuk suppe har hentet tabellen fra hver side. Pandas har gemt dataene fra hver tabel i en dataramme. Hver dataramme er et element i datalisten. De individuelle tabeldataframes skal nu flettes til en stor dataframe. Dataene konverteres derefter til JSON-format med 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')

Nu opretter Python JSON-datafilen. Den er klar til brug!

#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()

Den automatiserede proces er hurtig

Den automatiserede webskrabeproces beskrevet ovenfor fuldføres hurtigt. Selenium åbner et browservindue, som du kan se fungerer. Dette giver mig mulighed for at vise dig en skærmoptagelsesvideo af, hvor hurtig processen er. Du ser, hvor hurtigt scriptet følger et link, griber dataene, går tilbage og klikker på det næste link. Det gør hentning af data fra hundredvis af links et spørgsmål om encifrede minutter.

Den fulde Python-kode

Her er den fulde Python-kode. Jeg har medtaget en import til tabulat. Det kræver en ekstra kodelinje, der vil bruge en tabel til at udskrive dataene til din kommandolinjegrænseflade:

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()

Konklusion

Webskrabning med Python og Beautiful Soup er et fremragende værktøj at have inden for dit skillset. Brug webskrabning, når de data, du har brug for at arbejde med, er tilgængelige for offentligheden, men ikke nødvendigvis let tilgængelige. Når JavaScript leverer eller "skjuler" indhold, vil browserautomation med Selenium sikre, at din kode "ser", hvad du (som bruger) skal se. Og endelig, når du skraber tabeller fulde af data, er pandaer Python-dataanalysebiblioteket, der håndterer det hele.

Reference:

Den følgende artikel var en nyttig reference til dette projekt:

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

Kontakt mig når som helst på LinkedIn eller Twitter. Og hvis du kunne lide denne artikel, så giv den et par klapper. Jeg vil oprigtigt sætte pris på det.

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

Dave Gray (@yesdavidgray) | Twitter

De seneste tweets fra Dave Gray (@yesdavidgray). Instruktør @FHSUInformatics * Udvikler * Musiker * Iværksætter * ...

twitter.com