웹페이지 읽어오기 가이드

정말 오랫만에 글을 씁니다. 그간 여유가 좀 없었기도 하지만, 코딩할 계기도 별로 없었습니다. 반성...
요즘 논문 작업 때문에 다시 웹을 만지작 거리고 있습니다. 일을 하던 중에 여러분도 잘 모르겠다는 생각이 드는 것이 있어서 그것을 가지고 글을 씁니다.
오늘의 주제는 "User-Agent!". 웹 페이지를 크롤링하면 반드시 User-Agent를 남겨야 합니다. 예의..에 해당되기도 하고 서버에서 여러분을 거부하는 사태를 사전에 조금이나마 막을 수 있는 방법이기도 합니다.
R은 여러 패키지로 이루어져 있습니다. 그런데 User-Agent를 컨트롤 하기는 조금 복잡합니다. 웹을 검색해보면 여러 대안들이 나오지만, 엉터리도 좀 있고 해서 제가 정리해보겠습니다.

일단, 여러분 브라우저에 다음과 같이 입력해서 결과를 보세요.
http://httpbin.org/user-agent
저 같은 경우에 결과가
{
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"
}

이렇게 나옵니다. 이것이 User-Agent입니다.

R의 httr 페키지는 user_agent를 다루는 함수를 포함하고 있습니다. 예를 들어,

R> header = httr::user_agent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36")

이렇게 하면 User-Agent를 알려주는 헤더를 작성합니다.
GET()명령어를 써서 서버에 request를 합시다.

R> request_result = httr::GET("http://www.naver.com",header)

서버가 잘 반응했는지 안했는지 알고 싶지요?

R> request_result$status_code == 200 [1] TRUE
코드가 200이면 정상적으로 반응한 것입니다.

패키지 rvest로 파싱(parsing)을 합시다.

R> rvest_parsed_page = xml2::read_html(request_result)
R> all_anchors = rvest_parsed_page %>% rvest::html_nodes("a")

패키지의 네임스페이스(예를 들어, xml2::)를 모두 밝혔습니다. 여러분 보기 좋으라고...

GET을 다루는 좀 더 안전한 코딩은 다음과 같습니다. 해석은 각자 알아서 ㅋ.ㅋ 커피가 식어요....

R> emulate_browser <- function(url.code) {
  header = httr::user_agent("Mozilla/5.0 (Windows NT 10.0; WOW64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36")
  try = 2
  while(1) {
    if(try <=0) {
      result = NA
      break
    }
    result = httr::GET(url.code,header,httr::timeout(60))
    if(result$status_code == 200) {
      break
    } else {
      try = try - 1
      cat("Error Code =",result$state_code,"\n")
          cat(result,try,"remaining...\n",sep=" ")
          Sys.sleep(10)
    }
  }
          return(result)


한글 윈도우 사용자들이 가끔씩 저에게 물어보는 질문이 "한글이 깨집니다"인데... rvest에서 직접 이 문제를 다룰 수 있는 방법은 없습니다. 인터넷에 encoding= 옵션을 건드리면 되는 것처럼 나와 있지만 아닙니다.. ㅋㅋ

제가 사용하는 방법을 소개하면서 글을 끝낼까 합니다. 다음과 같은 함수를 하나 만듭시다.

html_hangul <- function(x) {
    txt <- x %>% rvest::html_text()
    stringr::str_conv(txt,'utf-8')
}

예를 들어 네이버의 앵커를 가져온다면

R> xml2::read_html(emulate_browser("http://www.naver.com")) %>% rvest::html_nodes('a') %>% html_hangul()

결과물은
[1] "뉴스스탠드 바로가기"
[2] "주제별캐스트 바로가기"
[3] "타임스퀘어 바로가기"
...
이렇습니다.

댓글

이 블로그의 인기 게시물

Bradley-Terry Model: paired comparison models

R에서 csv 파일 읽는 법

xlwings tutorial - 데이터 계산하여 붙여 넣기