2017-12-15 15 views
1

) 이것은 웹 스크래핑에 대한 첫 번째 시도입니다. 이 웹 페이지에서 테이블 목록 (열 이름 : 오일 & 가스 테이블)을 추출하려고합니다. Oil and Gas Data. 해당 상태의 링크 Alabama Data을 사용하여 한 주에 대한 데이터를 쉽게 추출 할 수있었습니다. 그러나 모든 주에 대한 데이터를 추출 할 수있는 프로그램이 필요하여 HTML 데이터에 표시된대로 유지해야합니다. 패키지를로드했습니다 RCurl, XML, rlist 및 purrr 이전의 유사한 게시물을 기반으로합니다.하이퍼 링크가 포함 된 웹 페이지에서 여러 테이블 추출 (R

How can I use R (Rcurl/XML packages ?!) to scrape this webpage?이 솔루션은이 게시 된 이후 완료는, 그러나, 문제의 웹 페이지는 아마 변경 보인다 (I 모방하려했지만 할 수 없었다)

R: XPath expression returns links outside of selected element . 어떻게 그들은 모두 "stateinitials_table.html"를 포함하기 때문에 XPath는 15의 목록

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

view source는 "al_table.html"에 대한 출력은 "al_table.html"알라바마을 위해 같이 내 필요한 테이블을 추출하는 데 사용할 수 데이터 프레임은 15 년 동안. 26 rows817 columns, 15 data frames 1 for each year

그래서 나는

메인 웹 링크의 모든 테이블을 추출하는 기능 (readHTMLTable 대 XPath는 바람직 XPath는)를 확인해야합니다. 웹 페이지에 표시된대로 주와 연도별로 '표시'해야합니다. (현재 쓸데없는 열과 행을 정리하는 것에 대해 신경 쓰지 않음)

+0

엑셀 파일이나 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의 태그와 비교하면 이해가됩니다. colspan 속성없이 모든 <tr>의 찾기 만 상태에 대한 권리 클래스와 링크 모두가 <tr>의 남은 선택 : 그것은 데이터 프레임에서의

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 

은 깔끔하고 편리한 유지.

아래에 비트를 입력해야하지만 그 기능을 표시하기 전에 반복을 설명해야합니다.

각 링크를 반복해야합니다. 각 반복에서, 우리 :

  • 요구 사항이 EIA의 서버 부하보다 더 중요하지 않습니다 일시 정지 이후
  • 그들은 두 가지 정보를 보유하기 때문에 우리가 (주 + 년을 필요로하는 모든 "지점"<div>의를 찾아 해당 주 + 1 년 동안의 데이터 표).
  • 좋은 데이터 프레임에

오히려 혼란까지 익명 함수보다 우리가 (이 반복자가 작동하기 전에 정의해야 다시) 다른 함수에서 해당 기능을 놓을 게요을 모두 마무리 :

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 코드를 당신이 그것을 가지고 grok 수 있도록하기 위해 기능 후에 와서 : 작동,

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이 제안한 다른 웹 페이지를 스크랩하기 전 언젠가

+0

크롤링 지연이 없습니까? 서버/네트워크 소유자 $보다 시간이 중요합니다. – hrbrmstr

+0

@hrbrmstr 포인트 잘 지적! – Prem