【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 }