【GAS】複数ページのスクレイピング
前回はGASでスクレイピングする基本的な方法を解説しました。
この記事ではGoogle Apps Script(GAS)で複数ページをスクレイピングする
スクレイピングでWebサイト情報を取得するシーンでは、サイトの複数ページに処理を実行したり、動的に条件を指定して結果を取得したい場合が多いかと思います。
この記事では、事前に準備していたURLリストに対して、複数回のスクレイピング処理を実行するコードを解説したいと思います。
・まずはスクレイピング用の関数を作成
・スクレイピング対象にしたい複数のurlをリスト化した配列を用意
・urlリストの回数分ループ構文を回してスクレイピングを実行する
・スレッドシートから読み込んだurlリストでも応用可能
1ページだけをスクレイピングするコード
前回同様にクックパッドさんのレシピページを対象にしてみます。
前回のコードを少し書き換えて、複数回処理実行中にエラーが発生しても次のページを読みにいけるように、try~catch構文で処理を分岐しています。
function Scraping() {
const url = "https://cookpad.com/recipe/7018658";
const contentText = UrlFetchApp.fetch(url).getContentText('utf-8');
try{
let ingredients = Parser.data(contentText).from('<span class=\'name\'>').to('</span>').iterate();
console.log(ingredients);
}catch (e) {
console.log((index+1)+"回目の処理でエラーになりました");
}
}
[ '卵',
'白はんぺん',
'砂糖',
'<a class="cookdict_ingredient_link" href="/cooking_basics/search/%E7%99%BD%E3%81%A0%E3%81%97">白だし</a>\n' ]
食材にリンクが入っていることもあり違和感感じる方は、同じようにParserライブラリを使って除外処理をしてみてください。
さて、これでレシピページに含まれている食材のリストを取得することができました。
リンク数分のスクレイピングを実行する
別の関数から上のScrapingを呼び出せるようにして、urlのリストをループで回してみます。
function Cookpad(){
let recipes = ['https://cookpad.com/recipe/7018658',
'https://cookpad.com/recipe/6578580',
'https://cookpad.com/recipe/6937498'];
recipes.forEach(function(value,index){
let recipesList = Scraping(value,index);
console.log(recipesList);
})
}
function Scraping(url,index) {
const contentText = UrlFetchApp.fetch(url).getContentText('utf-8');
try{
let meal = Parser.data(contentText).from('<h1 class=\'recipe-title fn clearfix\'>').to('</h1>').build().replace(/\n/g,'');
let ingredients = Parser.data(contentText).from('<span class=\'name\'>').to('</span>').iterate();
return ['料理'+ (index+1) ,meal,ingredients];
}catch (e) {
console.log((index+1)+"回目の処理でエラーになりました");
}
}
[ '料理1',
'オーブンで簡単伊達巻',
[ '卵',
'白はんぺん',
'砂糖',
'<a class="cookdict_ingredient_link" href="/cooking_basics/search/%E7%99%BD%E3%81%A0%E3%81%97">白だし</a>\n' ] ]
[ '料理2',
'伊達巻き',
[ 'はんぺん',
'たまご',
'★砂糖',
'<a class="cookdict_ingredient_link" href="/cooking_basics/search/%E3%81%BF%E3%82%8A%E3%82%93">★みりん</a>\n',
'★塩',
'<a class="cookdict_ingredient_link" href="/cooking_basics/search/%E9%BA%BA%E3%81%A4%E3%82%86">★麺つゆ(3倍濃縮)</a>\n',
'サラダ油' ] ]
[ '料理3',
'はんぺんのチーズはさみ焼き',
[ 'はんぺん',
'ベーコン',
'とろけるスライスチーズ',
'小麦粉',
'卵',
'<a class="cookdict_ingredient_link" href="/cooking_basics/search/%E3%83%91%E3%83%B3%E7%B2%89">パン粉</a>\n',
'<a class="cookdict_ingredient_link" href="/cooking_basics/search/%E6%B2%B9">油(揚げ用)</a>\n',
'ケチャップ' ] ]
リストの要素数回ループ
function Cookpad(){
let recipes = ['https://cookpad.com/recipe/7018658',
'https://cookpad.com/recipe/6578580',
'https://cookpad.com/recipe/6937498'];
recipes.forEach(function(value,index){
let recipesList = Scraping(value,index);
console.log(recipesList);
})
}
まずは3つのURLを格納して、recipesという配列を作ります。その要素の数(3)だけforEach()構文でループさせ、すでに作成してあるScraping()という関数を実行させます。
この際、各ループで要素の値とインデックス番号をScraping()の引数に使いました。
また、呼び出したScrapingで返り値としているいる[料理名+食材]のリストをrecipesListという変数に格納します。
引数の値を用いてスクレイピングの実行
Scraping内部での処理は前回同様で、引き渡されたurlを使ってスクレイピングを実行します。
function Scraping(url,index) {
const contentText = UrlFetchApp.fetch(url).getContentText('utf-8');
//料理名の取得
var meal = ingredients = Parser.data(contentText).from('<h1 class=\'recipe-title fn clearfix\'>').to('</h1>').build().replace(/\n/g,'');
//食材リストの取得
let ingredients = Parser.data(contentText).from('<span class=\'name\'>').to('</span>').iterate();
料理名と食材リストの配列を返す
料理番号、料理名、食材リストを配列に格納してScraping()を終了します。
return ['料理'+ (index+1) ,meal, ingredients];
以上、GASで複数ページのスクレイピングを実行してみました。
まとめ
この記事では、複数ページのスクレイピングを実行するGASを解説しました。
・まずはスクレイピング用の関数を作成
・スクレイピング対象にしたい複数のurlをリスト化した配列を用意
・urlリストの回数分ループ構文を回してスクレイピングを実行する
・スレッドシートから読み込んだurlリストでも応用可能
上記を応用すれば、今まで人力で行っていた調査なども、スプレッドシートに読み込みたいページのリストを用意して自動でスクレイピングを実行することで大幅に工数が削減できるかもしれません。
スプレッドシートでURLのリストを読み込んで実行結果もスプレッドシートに書き出す記事を公開しました!