Dies ist eher ein Blog-Post oder Tutorial als eine SO-Antwort, aber ich kann auch den Wunsch zu lernen schätzen und arbeite auch an einem Buch für dieses Thema und das scheint wie ein gd-beispiel.
library(rvest)
library(tidyverse)
Wir werden mit der Top-Level-Seite starten:
pg <- read_html("https://www.eia.gov/naturalgas/archive/petrosystem/petrosysog.html")
Jetzt werden wir einen XPath verwenden, die uns nur Tabellenzeilen bekommt, die Zustandsdaten in ihnen haben. Vergleichen Sie die XPath-Ausdrücke mit den Tags im HTML-Code. Dies sollte sinnvoll sein. All <tr>
s ohne colspan
Attribute und nur wählen verbleibenden <tr>
s, die sowohl die richtige Klasse und einen Link zu einem Staat haben:
states <- html_nodes(pg, xpath=".//tr[td[not(@colspan) and
contains(@class, 'links_normal') and a[@name]]]")
data_frame(
state = html_text(html_nodes(states, xpath=".//td[1]")),
link = html_attr(html_nodes(states, xpath=".//td[2]/a"), "href")
) -> state_tab
Es in einem Datenrahmen ist, damit es ordentlich und handlich.
Sie müssen das nächste Bit unter die Funktion stellen, die danach kommt, aber ich muss die Iteration erklären, bevor ich die Funktion zeige.
Wir müssen über jede Verbindung iterieren. In jeder Iteration wir:
- Pause, da Ihre Bedürfnisse sind nicht wichtiger als Serverbelastung der EIA
- finden alle „Zweig“
<div>
s, da sie zwei Informationen halten wir brauchen (den Zustand + Jahr und die Datentabelle für diesen Zustand + Jahr).
- es wickeln alle in einem netten Datenrahmen
Anstatt Unordnung auf die anonyme Funktion bis wir diese Funktionalität in einer anderen Funktion gesetzt werden (wieder, die vor diesem Iterator definiert werden muss, funktioniert):
pb <- progress_estimated(nrow(state_tab))
map_df(state_tab$link, ~{
pb$tick()$print()
pg <- read_html(sprintf("https://www.eia.gov/naturalgas/archive/petrosystem/%s", .x))
Sys.sleep(5) # scrape responsibly
html_nodes(pg, xpath=".//div[@class='branch']") %>%
map_df(extract_table)
}) -> og_df
Dies ist der harte Arbeiter des Bündels. Wir müssen alle State + Year-Labels auf der Seite finden (jeweils in einer <table>
), dann müssen wir die Tabellen mit Daten in ihnen finden. Ich nehme die Freiheit der Erklärungs Klappentext am Boden jeder Entfernung und auch jeweils in eine tibble
drehen (aber das ist nur meine Klasse Vorliebe):
extract_table <- function(pg) {
t1 <- html_nodes(pg, xpath=".//../tr[td[contains(@class, 'SystemTitle')]][1]")
t2 <- html_nodes(pg, xpath=".//table[contains(@summary, 'Report')]")
state_year <- (html_text(t1, trim=TRUE) %>% strsplit(" "))[[1]]
xml_find_first(t2, "td[@colspan]") %>% xml_remove()
html_table(t2, header=FALSE)[[1]] %>%
mutate(state=state_year[1], year=state_year[2]) %>%
tbl_df()
}
Re-Einfügen der aforeposted Code nur um sicherzustellen, dass Sie grok es hat nach der Funktion kommen:
pb <- progress_estimated(nrow(state_tab))
map_df(state_tab$link, ~{
pb$tick()$print()
pg <- read_html(sprintf("https://www.eia.gov/naturalgas/archive/petrosystem/%s", .x))
Sys.sleep(5) # scrape responsibly
html_nodes(pg, xpath=".//div[@class='branch']") %>%
map_df(extract_table)
}) -> og_df
Und es funktioniert (Sie sagten, Sie die endgültige Bereinigung separat tun würde):
glimpse(og_df)
## Observations: 14,028
## Variables: 19
## $ X1 <chr> "", "Prod.RateBracket(BOE/Day)", "0 - 1", "1 - 2", "2 - 4", "4 - 6", "...
## $ X2 <chr> "", "||||", "|", "|", "|", "|", "|", "|", "|", "|", "|", "|", "|", "|"...
## $ X3 <chr> "Oil Wells", "# ofOilWells", "26", "19", "61", "61", "47", "36", "250"...
## $ X4 <chr> "Oil Wells", "% ofOilWells", "5.2", "3.8", "12.1", "12.1", "9.3", "7.1...
## $ X5 <chr> "Oil Wells", "AnnualOilProd.(Mbbl)", "4.1", "7.8", "61.6", "104.9", "1...
## $ X6 <chr> "Oil Wells", "% ofOilProd.", "0.1", "0.2", "1.2", "2.1", "2.2", "2.3",...
## $ X7 <chr> "Oil Wells", "OilRateper Well(bbl/Day)", "0.5", "1.4", "3.0", "4.9", "...
## $ X8 <chr> "Oil Wells", "AnnualGasProd.(MMcf)", "1.5", "3.5", "16.5", "19.9", "9....
## $ X9 <chr> "Oil Wells", "GasRateper Well(Mcf/Day)", "0.2", "0.6", "0.8", "0.9", "...
## $ X10 <chr> "", "||||", "|", "|", "|", "|", "|", "|", "|", "|", "|", "|", "|", "|"...
## $ X11 <chr> "Gas Wells", "# ofGasWells", "365", "331", "988", "948", "867", "674",...
## $ X12 <chr> "Gas Wells", "% ofGasWells", "5.9", "5.4", "16.0", "15.4", "14.1", "10...
## $ X13 <chr> "Gas Wells", "AnnualGasProd.(MMcf)", "257.6", "1,044.3", "6,360.6", "1...
## $ X14 <chr> "Gas Wells", "% ofGasProd.", "0.1", "0.4", "2.6", "4.2", "5.3", "5.4",...
## $ X15 <chr> "Gas Wells", "GasRateper Well(Mcf/Day)", "2.2", "9.2", "18.1", "30.0",...
## $ X16 <chr> "Gas Wells", "AnnualOilProd.(Mbbl)", "0.2", "0.6", "1.6", "2.0", "2.4"...
## $ X17 <chr> "Gas Wells", "OilRateper Well(bbl/Day)", "0.0", "0.0", "0.0", "0.0", "...
## $ state <chr> "Alabama", "Alabama", "Alabama", "Alabama", "Alabama", "Alabama", "Ala...
## $ year <chr> "2009", "2009", "2009", "2009", "2009", "2009", "2009", "2009", "2009"...
Gibt es einen Grund, warum Sie nicht die Excel-Datei oder die APIs verwenden? – hrbrmstr
@hrbrmstr Ich möchte etwas Web Scraping lernen, ich bin mit Öldaten und R. vertraut. – Poppinyoshi