2017-12-15 20 views
1

これはウェブスクレイピングで初めての試みです。このウェブページからテーブルのリスト(カラム名:オイル&ガステーブル)を抽出しようとしています。 Oil and Gas Data。その状態のリンクAlabama Dataを使用すると、1つの状態のデータを簡単に抽出できました。しかし、私は、すべての州のデータを抽出し、HTMLデータに示されているようにそれらを年ごとに保つことができるプログラムが必要です。私はパッケージをロードしましたRCurl、XML、rlistとpurrr以前に似た投稿に基づいています。ハイパーリンクを含むウェブページから複数のテーブルを抽出するR

How can I use R (Rcurl/XML packages ?!) to scrape this webpage?このソリューションは、完全に見え、それが掲載されて以来、しかし、問題のあるWebページは、おそらく(私がエミュレートしようとしましたが、できなかった)

R: XPath expression returns links outside of selected elementを変更しました。どのように私は、これは15のリスト「al_table.html」のために出力されview source

theurl <- getURL("https://www.eia.gov/naturalgas/archive/petrosystem/al_table.html",.opts = list(ssl.verifypeer = FALSE)) 
tables <- readHTMLTable(theurl) 
tables <- list.clean(tables, fun = is.null, recursive = FALSE) 
berilium<-tables[seq(3,length(tables),2)] 

「al_table.html」彼らはすべてのアラバマのためのように「stateinitials_table.html」を含んでいるので、私の必要なテーブルを抽出するためのXpathを使用することができますデータフレーム15年間。 26 rows817 columns, 15 data frames 1 for each year

は、だから私は、

がメインのWebリンクからすべてのテーブルを抽出するための関数(readHTMLTable対のXpath、望ましいのXpath)を作成する必要があります。そして、ウェブページに表示されているように、州と年によって「マークされている」必要があります。 (現在は無用列と行のクリーンアップを懸念していない)

+0

ExcelファイルまたはAPIを使用していない理由はありますか? – hrbrmstr

+0

@hrbrmstr私はいくつかのウェブスクレイピングを学びたいと思っています。私はオイルデータとRに精通しています。 – Poppinyoshi

答えて

2

これはSO答えが、私は学ぶ意欲をも認めることができ、また、この非常にトピックをブックに取り組んでいますよりも、ブログの記事やチュートリアルの詳細ですこれはgdの例のようです。

library(rvest) 
library(tidyverse) 

我々はトップレベルのページから始めましょう:

pg <- read_html("https://www.eia.gov/naturalgas/archive/petrosystem/petrosysog.html") 

今、私たちは私たちだけそれらに状態データを持つテーブルの行を取得するXPathを使用します。 XPath式をHTMLのタグと比較すると意味があります。それはきちんとして便利な、それを維持するために、データフレームにあります

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 

:すべて<tr>colspan属性なしとだけは右のクラスと状態へのリンクの両方を持っている<tr>の残りを選択して下さい。

の下には、の後ろにある機能がありますが、その機能を示す前に繰り返しを説明する必要があります。

各リンクを反復処理する必要があります。各反復で、我々:

  • 一時停止ニーズは、EIAのサーバーの負荷
  • よりも重要ではないので、彼らは私たちが必要とする二つの情報(状態+年を保持するので、すべての「ブランチ」<div>のを見つけ、前記状態+年のデータテーブル)。
  • 素敵なデータフレームに匿名関数アップ

よりもむしろ混乱をそれをすべてを包む、我々は(このイテレータが動作する前に定義される必要がある、再び)別の関数内でその機能を入れます。

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 

これは束の勤労者です。ページの各州+年度のラベル(それぞれが<table>に入っています)を見つける必要があります。次に、その中にデータがあるテーブルを見つける必要があります。私はそれぞれの下部に説明宣伝文句を除去する自由を取るともtibbleにそれぞれを回す(それはちょうど私のクラスの好みです):

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

} 

だけ確保するためにaforepostedコードを再貼り付けるあなたはそれを完全に理解しています関数の後に来る:

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 

そして、それは動作します(あなたが個別に最終的なクリーンアップを行うだろうと言った):

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"... 
+0

これは素晴らしいです。私はもっ​​と勉強した後にあなたに戻ってきます。あなたの本に幸運を祈る。 – Poppinyoshi

1

は、この情報がお役に立てば幸いです!

library(rvest) 
library(dplyr) 

main_page <- read_html("https://www.eia.gov/naturalgas/archive/petrosystem/petrosysog.html") 
state <- main_page %>% 
    html_nodes(xpath='//td[contains(@width, "110")]') %>% 
    html_children() %>% 
    html_text() 
state_link <- main_page %>% 
    html_nodes(xpath='//td[contains(@width, "160")]') %>% 
    html_children() %>% 
    html_attr('href') 

final_data <- list() 
for (i in 1:length(state)){ 
    child_page <- read_html(paste0("https://www.eia.gov/naturalgas/archive/petrosystem/",state_link[i])) 
    Sys.sleep(5) 

    child_page_stateAndYear <- child_page %>% 
    html_nodes(xpath = '//td[@class="c SystemTitle" and @style=" font-size: 14pt; color: #CC0000;"]') %>% 
    html_text 
    child_page_table <- lapply(
    (child_page %>% 
     html_nodes(xpath = '//table[contains(@class, "Table")]') %>% 
     html_table()), 
    function(x) x[-nrow(x),]) 
    final_data[[state[i]]] <- setNames(child_page_table, child_page_stateAndYear) 

    print(paste('Scrapped data for', state[i], '...')) 
    flush.console() 
} 
print('Congratulation! You have finished scrapping the required data!') 

names(final_data) 
names(final_data[[1]]) 

final_data(状態の即ち年単位の表形式データ)を34個の素子(メインウェブページ上で利用可能な、すなわち状態)を有し、各要素は、テーブルのリストです。

編集:がスリープ状態にロジックを追加しました:あなたは「アラバマ2009」に属するデータを持つようにしたいのであれば、その後ちょうど

final_data[['Alabama']]['Alabama 2009'] 

(あなたがデータクリーニングの少しを行う必要がある場合があります)を入力します@hrbrmstrによって提案された別のWebページを廃棄する前にいつか

+0

クロールの遅延はありませんか?あなたの時間は、サーバー/ネットワークの所有者$よりも重要です。 – hrbrmstr

+0

@hrbrmstrポイントよく記載! – Prem

関連する問題