データ分析メモと北欧生活

旧Untitled Note. データ分析、計量経済・統計とR、水産管理、英語勉強、海外生活などについて備忘録や自分の勉強のOutputの場所として

MENU

【R】スクレイピング時のループで404エラーが出た時に止まるのを避ける

ちょっと必要になって、ウェブサイト上のテーブルをまとめてダウンロードするという作業が必要になった。

だいたいPythonとかでやるのが主流なようだが、私はR使いなのでRでやる方法を探しているとrvestというパッケージがよいらしい。

rvestの基本的な使い方に関しては、Shohei Doiさんのノートが大変参考になった。
shohei-doi.github.io


さて、問題は同じようなウェブサイトページにURLをループで取得したい時に、時々ページ自体が存在せず、404 Error Not Foundのエラーが出ることがある。

これが困るのは、そのエラーが出た時点でループが止まってしまうことだ。とりあえず404があれば無視して次に行ってほしいので、どうすればいいかを調べてみたことをメモっておく。

tryCatchを使う。

以下のコードが実際に私が書いたコードの一部である。

ある記事に番号が振られており、1から300まで回して中にある表を取得しようとしているのだが、
不規則に404 Not Foundがでてくるので、単純にループを回すとそこで止まってしまう。

まず、delayedAssignでdo.nextという変数にnextの関数を割り振る。nextはloop内で出てくると、次のループに飛ばしてくれる命令である。

tryCatchは、1つ目の引数を評価して、エラーなど異常な条件が出ると、それに対して対応を決められる関数である。ここではrvestのread_htmlの関数を評価しているので、これにエラーがでると次のerror =で対応を決めている。
ここでは、もしURLが404 Not Foundでエラーが出た場合、"URL Not Found, skipping"というメッセージを表示して、force(do.next)により、次のループに飛ぶように命令している。

library(tidyverse)
library(rvest)

yr = 2017  #extracting year

list_tables = list()  # make list to store the result

for(i in 1:300){ # j-meldings up to 300 per year? maybe more in other years...
  
 url <- paste0("https://www.fiskeridir.no/Yrkesfiske/Regelverk-og-reguleringer/J-meldinger/Utgaatte-J-meldinger/J-",i,"-",yr)


 delayedAssign("do.next", {next})
 
 # use tryCatch to avoid stopping by error reading 404 page. 
 html <- tryCatch(
   read_html(url),
   error=function(e) {print("URL Not Found, skipping")
     force(do.next)})

 # check if <head> and <body> are properly read.
 
 # read html file from the url
 html <- url %>% read_html

 # print the number of meldings 
 print(paste0("melding ",i," is successfully read"))
 
# 2.1. check the title of melding
 
 # if the read html is not about the cod fishery, skip to next loop
 html_title <- html %>%
   html_node("h1") %>% 
   html_text() %>%
   str_detect(pattern = "Forskrift om regulering av fisket etter torsk, hyse og sei nord for 62°N")
 
 if(!html_title){
   next
 }