今回はBOOK☆WALKERのデイリーランキングを取得し、毎日Googleスプレッドシートに自動追記するGASを紹介します。
#データのソース
ランキングはこちらのURLから見れます。
URL(https://bookwalker.jp/rank/?mode=daily
)の末尾?mode=daily
でデイリーランキングを指定しています。この部分を ?mode=weekly
にすると週間ランキングに、 ?mode=monthly
にすると月間ランキングにアクセスできます。
#方法
今回はソースコードからランキング(と評価・レビュー数)を取得します。BOOK☆WALKERのランキングのソースコードは少し変わっています。前半部分にJSONファイルで必要な情報を書いていて、そこからJSで各作品の情報を引っ張ってきています(多分)。
簡単に言えば、ランキングの情報が書いてあるJSONを取得すればいいだけですね。
let url = "https://bookwalker.jp/rank/?mode=daily";
let html = UrlFetchApp.fetch(url).getContentText('UTF-8');
GASのUrlFetchAppクラス(fetchメソッド)を使います。
.getContentText()
でソースコード(HTML)を文字列として取得します。
ソースコードの中でも、必要なのはJSONの部分だけです。
そのため、余計な前後の部分を省く必要があります。
まずは、Parserライブラリを追加しましょう(やり方はこちらを参照)。
必要なJSONは、ソースコードの中の<script type="application/ld+json">
と</script>
というタグの間にあります。
let list = Parser
.data(html)
.from('<script type="application/ld+json">')
.to('</script>')
.build();
let jsonData = JSON.parse(list)
.from()
と.to()
で切り取る部分を指定します。
list
は文字列なので、扱いやすいようにJSON.parse(list)
でJSON形式に直してあげましょう。
これで変数jsonData
にJSON形式のランキング情報を格納できました。
それでは、JSONの形式を詳しく見ていきましょう。
{
"@context": "http://schema.org",
"@type": "Product",
"name": "僕のヒーローアカデミア 33",
"image": "https://c.bookwalker.jp/5759094/t_700x780.jpg",
"description": "ヒーローへの信頼が揺らいでいる現状では生徒は不安を抱え、故に私たち教員は全力で彼らを守らなければならない! 雄英とは安心していつでも戻ってこられる場所。さあ! 君たちの声を…想いを…彼に届けるのさ! “Plus Ultra”!!",
"url": "https://bookwalker.jp/deab48af8f-6549-4000-8b56-9dcb2b18459d/",
"category": "マンガ",
"brand": {
"@type": "Brand",
"name": "集英社"
},
"offers": {
"@type": "Offer",
"price": 460,
"priceCurrency": "JPY",
"itemCondition": "http://schema.org/NewCondition",
"availability": "http://schema.org/InStock",
"seller": {
"@type": "Organization",
"name": "BOOK☆WALKER",
"logo": "https://bookwalker.jp/henry/pc/img/common/bw-logo.png",
"url": "https://bookwalker.jp/",
"sameAs": "https://twitter.com/BOOK_WALKER"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.9,
"reviewCount": 108,
"bestRating": 5,
"worstRating": 0
}
},
今回取得するのは作品名(name
)、評価(ratingValue
)、レビュー数(reviewCount
)を取得します。
ちなみに、今回の場合はそれぞれの項目が何を指しているのか、こちらで確認できます。
それでは、以上の3項目を配列に入れましょう。
let outputList = [] //配列を生成
let jsonLength = jsonData.length //JSONのデータ個数を取得
for (let i = 0; i < jsonLength; i++) { //for文を回す回数をJSONのデータ個数にする
let name = jsonData[i].name //i個目の作品の名前
let ratingValue = jsonData[i].aggregateRating.ratingValue //i個目の作品の評価
let reviewCount = jsonData[i].aggregateRating.reviewCount //i個目の作品のレビュー数
outputList.push([name, ratingValue, reviewCount])
}
しかし、このままではエラーが起きます。
なぜなら、すべての作品に評価とレビュー数があるとは限らないからです。
なので、このままだと評価・レビュー数がない作品を取得しようとすると以下のようなエラーが出ます。
TypeError: Cannot read property 'ratingValue' of undefined
そのため、エラーが発生した場合は、当該作品の評価を飛ばす必要があります。
さらに見出しを追加したコードは以下になります。
let date = new Date();
let today = Utilities.formatDate(date, 'JST', 'yyyy-MM-dd kk:mm:ss') //今日の日付を取得
let outputList = [[today, '評価', 'レビュー数']] //配列を生成し、配列の見出し(日付、評価、レビュー数)を挿入
let jsonLength = jsonData.length
for (let i = 0; i < jsonLength; i++) {
let name = jsonData[i].name
try {
ratingValue = jsonData[i].aggregateRating.ratingValue
} catch { //エラーが発生した場合は
ratingValue = "" //評価を空白に
}
try {
reviewCount = jsonData[i].aggregateRating.reviewCount
} catch { //エラーが発生した場合は
reviewCount = "" //レビュー数を空白に
}
outputList.push([name, ratingValue, reviewCount])
}
//console.log(outputList)で確認すると↓
//[ [ '2022-02-06 21:53:48', '評価', 'レビュー数' ],
// [ '僕のヒーローアカデミア 33', 4.9, 108 ],
// [ 'ザ・ファブル The second contact(2)', 4.8, 54 ],
// [ '【電子版】B\'s-LOG COMIC 2022 Feb. Vol.109', 5, 3 ],
// [ 'ラストギアス (6)', 4.3, 22 ],
// [ 'その着せ替え人形は恋をする 7巻', 4.8, 842 ],
// (以下省略)
ちなみに、変数を定義する際にlet
を外してグローバル変数としています。
これで、必要な情報は配列に挿入できましたので、あとはスプレッドシートに追加するだけです。
最終列の1つ右の列に毎日どんどんデータを追記していきたいです。
let daily = SpreadsheetApp.openById("スプレッドシートID").getSheetByName('シート名')
let lastCol = daily.getLastColumn() //最終列を取得
daily.getRange(1, lastCol + 1, 101, 3).setValues(outputList) //最終列の右の列に101行(データ数(100)+見出し)、3列(作品名、評価、レビュー数)のデータを書く
以上になります。完成したコードは以下です。
function bookwalkerDaily() {
let url = "https://bookwalker.jp/rank/?mode=daily";
let html = UrlFetchApp.fetch(url).getContentText('UTF-8');
let list = Parser
.data(html)
.from('<script type="application/ld+json">')
.to('</script>')
.build();
let jsonData = JSON.parse(list)
let date = new Date();
let today = Utilities.formatDate(date, 'JST', 'yyyy-MM-dd kk:mm:ss')
let outputList = [[today, '評価', 'レビュー数']]
let jsonLength = jsonData.length
for (let i = 0; i < jsonLength; i++) {
let name = jsonData[i].name
try {
ratingValue = jsonData[i].aggregateRating.ratingValue
} catch {
ratingValue = ""
}
try {
reviewCount = jsonData[i].aggregateRating.reviewCount
} catch {
reviewCount = ""
}
outputList.push([name, ratingValue, reviewCount])
}
let daily = SpreadsheetApp.openById("スプレッドシートID").getSheetByName('シート名')
let lastCol = daily.getLastColumn()
daily.getRange(1, lastCol + 1, 101, 3).setValues(outputList)
}
完成像の写真にある左端の順位は手動で1から100まで追加してください。
今回は以上となります!