読者から質問があり、「51位から100位まではどうやればいいか」というものでした。先回コードは1-10位までで1回のみだったので、おそらく2回ループを回すようなコードのイメージがつかなかったのかなと考えました。実際に、ループ処理では、1回目と2回目以降で全く考え方が異なります。1回のみであれば制御は1回オリジナルですが、ループであればより平準化というか効率的にという考えが求められるからですね。
実際に、先回記事のサンプルコードはループ処理が面倒だったのでやってなかったのですが、ループ処理を追加することで、50位までなら5回(10位までを5回)のようにして、100位までなら1回10件を10回繰り返すということで実現してみました。
ただ冷静に考えると、最後にまとめるのですが、本SearchAPIを使った対象件数がノーマルなGoogle検索と相当ずれていたりします。プログラムで検索したリクエスト結果とはいえ取得した1件目から10件目の後に、11件目から20件目・・・のようにしているわけですが、これが順位といっていいのかが疑問です。結論的にいえば、怪しいというかヒットの有無もずれていたりしていて、参考になるのかな?くらいです。というか、この検索APIをどう使うかなんですが、仮に検索結果を得られるという自動化みたいなことをやる場合、その結果はカスタム検索ということで「カスタム検索エンジン」の設定などでも変わってくるのだろうと考えられます。
さすがにそのカスタム検索設定まで突っ込んで調べていません。逆に分かることがあれば教えて頂ければ嬉しいです。
概要
今回やってみたのは、
- 先回記事の改造をして、100位までの結果を出せるようにした
- そもそもGoogle検索とAPI検索は結果的に妥当性があるのかを調べた
というところで、大きく2つです。
コード
細かい話は先回記事を見てみてください。
改造した点は以下のようになります。
- start_num(検索開始位置)、start_str(検索開始位置の文字列変換用)、j(検索ループ用)を新規追加
- リクエストURLにパラメタ「start」を付け、その変数に対してstart_strをセットする
- col_pos(セル行位置)を使い、セルに順に追加していく
- ループを回し1回目=1~10位、2回目=11位~20位、・・・以下、for jループ指定値まで回す(10なら10回、5なら5回)
- ループ最後に、start_numを+10増やして、1件目→11件目→21件目→31件目→41件目(50件目まで)→終了となる
インデントもしてなくて見づらくなってますが、
for (j = 0; j < 10; j++) {
のjループが肝です。 j<10が10回ループを回すという意図です。コードを実行する際はリクエスト数を無駄に減らすことになるので、ぜひ1など数を減らして実行して2などでループを確認しつつ試されるほうがいいでしょう。
Loggerなどのログはコメントアウトしているつもりですが消えてなかったすいません。
function main(){
//設定シートから設定情報を読み込む
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('config');
var word = sheet.getRange(2,2).getValue();
var start_num = 1;
var start_str = '';
var j = 0;
for (j = 0; j < 10; j++) {
start_str = start_num.toString();
var apiKey = 'xxx'; //apiキー
var apiUrl = 'https://www.googleapis.com/customsearch/v1/';
var query = '?q='+ encodeURIComponent(word);
query += '&cx=' + 'xxx';
query += '&start=' + start_str; //n件目から
query += '&key='+apiKey;
apiUrl = apiUrl + query;
var response = UrlFetchApp.fetch(apiUrl);
if (response.getResponseCode() !== 200) {
throw new Error('エラーのため取得できませんでした');
} else {
var res = JSON.parse(response);
}
//Logger.log(res);
//データを取得する
try {
//データシートを取得する
var sheet = spreadsheet.getSheetByName('data');
//検索合計数を取得する
var totalResults = res.queries["request"][0]["totalResults"].toString();
//取得した値をセルに書き込む
sheet.getRange(1,1).setValue(totalResults); //合計検索数
//10件ずつ情報を取得する
var col_pos = parseInt(start_num) + 3; //書き込み行を設定する
var titles =[];
var i = 0;
for (i = 0; i < 10; i++) {
titles.push([res.items[i]["title"].toString()]);
}
sheet.getRange(col_pos,2,10,1).setValues(titles); //配列で書き込む
//urlを取得する
var urls = [];
for (i = 0; i < 10; i++) {
urls.push([res.items[i]["link"].toString()]);
}
sheet.getRange(col_pos,3,10,1).setValues(urls); //配列で書き込む
//概要を取得する
var snippets = [];
for (i = 0; i < 10; i++) {
snippets.push([res.items[i]["snippet"].toString()]);
}
sheet.getRange(col_pos,4,10,1).setValues(snippets); //配列で書き込む
//Logger.log(snippets);
} catch(e) {
return e.toString();
}
start_num = parseInt(start_num) + 10;
//Logger.log(start_num);
}
}
留意点
本APIは1日100リクエストまでが無料であり、何度かテストコードをかいて試すと、例えば100位まで取るなら、10回ループ=10リクエストを1回実行で出すため、10回しか実行できないです。
検索結果の妥当性
そもそもCustom Search APIと普通のGoogle検索が合致するものなのか、別物ではないかということです。別物という認識のほうがいいと思っていて、仮に一緒に出来るならその設定があるはずでしょう。現状ではよく分かっていません。
以下気づいた点です。
1.カスタムサーチ検索結果の対象件数と、標準のGoogle検索では大きく対象件数がズレている
キーワード「アイデア」で検索した場合ですが、Google検索結果では、
2億8千万件というなかから検索したことになります。
一方、カスタムサーチ検索、つまり今回のコード(1-50位の結果を取得する)では、
1億5千万件程度であり、2分の1程度少ないです。これはカスタム検索でそもそもフィルタリングされているのか、動きが別なのかよく分かりません。
まず対象件数が違うということが確認出来ます。他のキーワードでも一緒かと思います。
2.順位はたまたま1-50位で50番目は合致したが、ところどころずれているため、カスタムサーチ検索結果の順位を「Google検索結果」と同様に扱うのは厳しい気がする。
続きですが、1-50位というところで、例えばGoogle検索結果でたまたま出てきた50番目であろうサイトは以下のサイトでした。
次にカスタムサーチ結果の場合ですが、
一致してる!と喜びたいのですが、前後もですが、合致するものもあるし、また順位自体は違っているようにも見えます。
3.明らかにヒットしてない結果もあるため、正直違うものという認識にしたほうが無難か
知っているサイトや見かけたサイトが明らかに出てこなかったりということもあります。単に対象件数が半分程度のため見えないのか、別検索の動きなのか、よく分かりません。
少なくとも、カスタムサーチ検索結果で1位だからGoogle検索でも1位とかって意味がなさそうです。というか保証できないという感覚です。1位でなく他順位でも同様ということですね。
アイデアの否定(笑)
先回記事に偉そうにアイデアを書いていました(笑)
1つは、検索結果をウォッチできるのではないかですが、これも結局は妥当性がどうなのってことで、あてにならない感じもします。他の考え方としては、どう妥当性を上げるかくらいでしょうか。
とはいえ、ループを回して取ってこれるということは出来たのでひとまずオッケーというところです。
自分で考えてみるのが大事というオチで
本サンプルもですが、カスタムサーチについては結局は自分で考えて何が分からないか、どういう意図でやるか、何を得たいかなどの考えることを詰めていく必要があります。
簡単にコードを書いてGASだからクラウド等有償なサービスを使わず出来るというのはありがたいことですが、一方で限界や出来ないこともあるわけですね。
検証してみた結果、あくまで習学のためにたまたま見つけたAPIを使ってみただけです。これをどう使うかとかは考えてないのですが、ニーズがあればまた検証したり追加で記事を書いたりもしてみます。なければこのままですね(笑)
あとはカスタムサーチ検索自体はサイトに設置して使うみたいな感じを想定しているのでAPIでどこまでやるかってよく分かってないですね。
何かヒントになれば幸いです。