Google検索をする場合、カスタム検索APIというものが使えます。これはたまにWebサイトで目にする(自治体サイトなどでは必ずある)、カスタム検索と同様のものかなと思っています。ちゃんと調べていませんが。
それはおいておいて、このカスタム検索APIを用いると、Google検索が出来るということでちょっとやってみました。
概要
今回やってみたのは、
- Google Custom Search APIの使用感はどうなのか
- GASを用いてさくっとコードが書けるものなのか
- GASのスプレッドシートあたりの理解を深める
- JSONを取得する際など、APIサービスをさくっと出来るものか
などを意識しつつやってみました。
コード
GASの理解としては、スプレッドシート→スクリプトエディタでのgsコードと、gsから作るスクリプトエディタは異なるという理解が必須です。ぱっと見でリンクしているか分からないのでこれどうなんでしょう。見えるところがあるかもしれません。
今回は、スプレッドシート→スクリプトエディタで追加しているので、それをやらずにgsからコードを作るとうまくいきません(実際にスクリプトエディタからリンクさせるには、スプレッドシートのIDを指定してシートを参照するやり方で出来ます)
わりとハマりやすいので注意ですね。
一枚のスプレッドシート(Excel的にはブックですよね)を作ったら、configシートとdataシートを作成しておきます。configシートは、「検索ワード」をセルに入れておき、そのワードで検索しています。configシートは、(2,2)とありますがこれはB2セルのことです。そこにワードがあればオッケーです。有無はチェックしていません。
dataシートは、A1に検索結果の該当数を無機質に出して、2列目に、「順位、title、url、概要」という感じに並べています。これは見やすいかどうかだけなのでなくても動作します。
function main(){
//設定シートから設定情報を読み込む
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('config');
var word = sheet.getRange(2,2).getValue();
var apiKey = 'xxxxx'; //apiキー
var apiUrl = 'https://www.googleapis.com/customsearch/v1/';
var query = '?q='+ encodeURIComponent(word);
query += '&cx=' + 'xxxxx'; //カスタム検索エンジンID
query += '&key='+apiKey;
apiUrl = apiUrl + query;
var response = UrlFetchApp.fetch(apiUrl);
if (response.getResponseCode() !== 200) {
throw new Error('エラーのため取得できませんでした');
} else {
var res = JSON.parse(response);
}
//データを取得する
try {
//データシートを取得する
var sheet = spreadsheet.getSheetByName('data');
//検索合計数を取得する
var totalResults = res.queries["request"][0]["totalResults"].toString();
//取得した値をセルに書き込む
sheet.getRange(1,1).setValue(totalResults); //合計検索数
//1位から10位のタイトル名
var titles =[];
var i = 0;
for (i = 0; i < 10; i++) {
titles.push([res.items[i]["title"].toString()]);
}
sheet.getRange(3,2,10,1).setValues(titles); //配列で書き込む
//urlを取得する
var urls = [];
for (i = 0; i < 10; i++) {
urls.push([res.items[i]["link"].toString()]);
}
sheet.getRange(3,3,10,1).setValues(urls); //配列で書き込む
//概要を取得する
var snippets = [];
for (i = 0; i < 10; i++) {
snippets.push([res.items[i]["snippet"].toString()]);
}
sheet.getRange(3,4,10,1).setValues(snippets); //配列で書き込む
} catch(e) {
return e.toString();
}
}
設定など
APIキーについては、今回のCustomSearchAPI用というよりも、GoogleのAPIコンソールでいえば、1プロジェクト毎に使うAPIを追加する形ですね。ただ使い方が異なれば違うので、まあ普通にAPIキーを取得してそれを使う感じです。
カスタム検索エンジンIDとは、cxパラメタに設定していますが、これはカスタム検索画面で作る必要があります。CSEはカスタムサーチエンジンなんでしょう。詳細な作り方は割愛しますが、ここで「追加したサイトを重視し、ウェブ全体を検索する」とすればウェブ全体の検索となるようです。画像検索など手を出していませんが出来るっぽいですね。また、この画面で検索エンジンIDボタンがあるのでそれを押せば取得できる値をcxの値に入れる必要があります。
カスタムサーチAPIでは、必須項目が、検索ワードのqと、カスタム検索エンジンIDのcx、そしてkeyのAPIキーの3つです。
あと、認証許可という意味では、外部APIにつなげるとか、スプレッドシートの操作をするなどの許可が必要です。自分だけで使うならいいですが、共有などもしする場合は気をつけたいところですね。
他の学び
色々学べたのでざっとメモしておきます。
- CustomSearchAPIは1日100リクエストなので貴重な感じ。実際にこれは無料版での形です。有料版は課金型となり、APIのダッシュボードを見るとリクエスト使用数なども確認できます。ちなみに1日の区切りは日本時間でいえば17時です。太平洋時間なので、そのあたりは地味に気づきづらいですね。気づいたら52リクエストも出していましたね(笑)
- 課金をすると、多分ですが、1日1000クエリで5ドルっぽいです。クエリ自体はエラークエリでもカウントされるので、単純に100回検索出来るとかってことでなく、プログラムでループで回すとかなら一瞬で100リクエストはいっちゃうでしょうね。
- スプレッドシートへの書き込みで、配列setvaluesが使えるのですが、配列は2次元配列というのはややはまりました。1次元配列でやってもダメなわけです。pushの仕方が分かりづらかったのですが、配列.push([入れる内容1,入れる内容2])みたいにやるといけます。縦に入れたいなら、コードにあるようにループで追加ですね。1次元配列でやってもとくにエラーが出るわけではないので気づきにくいですね。SetValueなどで一個ずつやってもいいですが、さすがにダルくなるので配列にしています。あとSetValuesの前にやってるgetRangeも書く前はわかりづらいですが、row,columnの順番で、オプションとしてRange的な意味のものを書いていく感じです。
- logger.log→Logger.logとか、大文字でないとログが出ないとかは、まあミスですけど、そういうのは地味に大事ですね。エラーが出ないのでログでないぞとか大騒ぎになります(笑)いやなら、デバッグ用にセルに出してもいいかも。msgboxはうざい感じで使ってません。
- URLエンコードはコンポーネントで簡単。コードでいえば、encodeURIComponent(対象文字列)で出来ます。いいですね。
- jsonのカギ括弧は配列なので配列番号を指定などに気をつける。カギ括弧と波括弧は見づらいのでJSON慣れてないとはまります。慣れてないながらやると、まあ見づらい。慣れればいいんでしょうけど、配列だと[0]など要素指定しないと、確かnullでなくobjectですって感じで何もtoStringされないから困りますね。
- JSONデータが取ってこれれば、あとはJSONで要素名検索して取ってくるだけなのでひと踏ん張りです。
{ "kind": "customsearch#search", "url": { ... }, "queries": { "request": [ ... ], "nextPage": [ ... ] }, "context": { ... }, "searchInformation": { ... }, "items": [ { "kind": "customsearch#result", "title": "LOHACO - お茶 通販 - 水・コーヒー・お茶・飲料", "htmlTitle": "LOHACO - <b>お茶</b> 通販 - 水・コーヒー・<b>お茶</b>・飲料", "link": "https://lohaco.jp/g2/51-5115/", "displayLink": "lohaco.jp", "snippet": "お茶(水・コーヒー・お茶・飲料)の通販ならLOHACO(ロハコ)!商品の価格や仕様、\nレビューなどをご覧いただけます。18時までのご注文で最短翌日お届け、1900円以上\nで基本配送料無料。LOHACO(ロハコ)はヤフーとアスクルがお届けするネット通販\nサイトです。", "htmlSnippet": "<b>お茶</b>(水・コーヒー・<b>お茶</b>・飲料)の通販ならLOHACO(ロハコ)!商品の価格や仕様、<br>\nレビューなどをご覧いただけます。18時までのご注文で最短翌日お届け、1900円以上<br>\nで基本配送料無料。LOHACO(ロハコ)はヤフーとアスクルがお届けするネット通販<br>\nサイトです。", "cacheId": "EdLTZHFWp7UJ", "formattedUrl": "https://lohaco.jp/g2/51-5115/", "htmlFormattedUrl": "https://lohaco.jp/g2/51-5115/", "pagemap": { "cse_thumbnail": [ { "width": "194", "height": "260", "src": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRXmMXJODkv5BWkdbcfWKGnwvI8QT6eAkY0Kf3toAYW2-pSYStkbcs_GezG" } ], "metatags": [ { "coverage": "Japan", "copyright": "Copyright ASKUL Corporation. All rights reserved.", "format-detection": "telephone=no" } ], "breadcrumb": [ { "url": "LOHACOホーム", "title": "LOHACOホーム" }, { "url": "水・コーヒー・お茶・飲料", "title": "水・コーヒー・お茶・飲料" }, { "title": "お茶" } ], "cse_image": [ { "src": "https://askul.c.yimg.jp/resource/c/prod/content/dam/lohaco-parts/category/food/51-5115/298830_bnr_296x396.jpg" } ] } }, { "kind": "customsearch#result", "title": "【楽天市場】お茶の通販", "htmlTitle": "【楽天市場】<b>お茶</b>の通販", "link": "https://search.rakuten.co.jp/search/mall/%E3%81%8A%E8%8C%B6/", "displayLink": "search.rakuten.co.jp", "snippet": "楽天市場-「お茶」534607件 人気の商品を価格比較・ランキング・レビュー・口コミで検討\nできます。ご購入でポイント取得がお得。セール商品・送料無料商品も多数。「あす楽」\nなら翌日お届けも可能です。", "htmlSnippet": "楽天市場-「<b>お茶</b>」534607件 人気の商品を価格比較・ランキング・レビュー・口コミで検討<br>\nできます。ご購入でポイント取得がお得。セール商品・送料無料商品も多数。「あす楽」<br>\nなら翌日お届けも可能です。", "cacheId": "Ca23-OAb3YoJ", "formattedUrl": "https://search.rakuten.co.jp/search/mall/お茶/", "htmlFormattedUrl": "https://search.rakuten.co.jp/search/mall/<b>お茶</b>/", "pagemap": { "cse_thumbnail": [ { "width": "198", "height": "198", "src": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQRSBHrbItD9HT1_rG85rRxFIlf9-vn3SmLpq9QgfsCptQpnAxeF9Y-aFM" } ], "metatags": [ { "viewport": "width=device-width, initial-scale=1.0", "dui:trace": "7b2938f6-9795-4833-851d-d8f13f8518d2" } ], "cse_image": [ { "src": "https://tshop.r10s.jp/soukaidrink/cabinet/campaign/mtm0001c_prd.jpg?fitin=198:198" } ] } }, { ... }, { ... }, { ... }, { ... }, { ... }, { ... }, { ... }, { ... } ] }
これはお茶で検索した時のサンプルです。このままJSONで使えるわけではないですが、CustomSearchAPIも「試しに使う」から、GUIベースで結果を試せるので便利です。APIライブラリから「Custom Search API」を選ぶと、「管理」か「このAPIを試す」というのが選べるので、このAPIを試すを選ぶといけます。
Services > CustomSearch API v1 というのが出てくるので、search.cse.listというものをクリックする(これがわかりづらい)と、テストフォームが出てきます。パラメタの赤文字が必須です。(これもやや見づらいw)
この試しに使うのは、さすがにコールしたカウントに入らないようです。ですのでパラメタ見てガチャガチャ試すときはまずこのテストフォームでURLパラメタを指定してちゃんと取ってこれるかやったほうがいいですね。
- numは指定しないと10件ぽいですが、Google検索的に2ページ目などはどうするかというと、startパラメタに11などとすれば、11~20の取得になるのでいけるかと思います。要するにリクエストを1回で10件なので、50件欲しいなら5回まわす必要があります。このコードではやってませんが、ループすればいいだけのはずです。
- コードにありますが、サイト名はtitleで、URLはlinkで、概要はsnippetのようです。メタタグに概要としてdescriptionがあればそれもあるっぽいですが、ないのは取れないでしょうからsnippetかなと。
- 設定シートと、データシートを分けるとかは、シート名を指定すればオッケーです。こうすると設定画面とデータ画面が分けられるので見やすくはなりますよね。
- GAS自体はjavascriptベースという感じで使いやすいのではないでしょうか。あと、GoogleAPIが色々あるので、うまく組み合わせれば色々とサービスが作れそうです。
アイデア
これを元にすれば色々と順位検索も出来そうです。
例えば、
- トリガーを用いて、毎日指定時刻などにキーワードで順位を検索してシートに記録していく(一週間毎に見るなど)→ただこれは結果的にGoogleのサーチコンソールと同様な感じがします(アクセスがないワードには対応できないので厳密には違うわけですが)
- 10位までしか取れないので、30位までなど取得件数を拡張してみる
当然ですが、GoogleAPIは他にもあるのでそれらで遊ぶと面白そうです。
振り返り
冒頭に上げた狙いについてはどうだったかですが、
Google Custom Search APIの使用感はどうなのか
検索を激しくするとかであればまず課金が必須かなと思います。どういうことをやるかによりますが、まあ無料版でも色々と出来そうかなという印象です。
GASを用いてさくっとコードが書けるものなのか
GASの癖というか、書き方みたいなものがあるかもしれませんが、javascriptの知識があればある程度いけそうかなと。最も何をしたいかによりそうです。GAS自体はAPI連携であるとか、色々なことが出来そうな印象が強いですね。
GASのスプレッドシートあたりの理解を深める
理解としては、上にも書いたスプレッドシートありきのGASと、スクリプトエディタのみのGASで注意が必要というところですね。これの違いが分からないとハマるのは必須ですね。あと、スプレッドシートの操作はVBAとかExcel操作が出来るならそこまではまらないはずというところです。
JSONを取得する際など、APIサービスをさくっと出来るものか
JSON取得は他のWebサービスやAPIでも普通のはずなので、そこらへんは重ねていくと理解が深まりそうです。APIサービスというかサンプルコードに近いですが、APIキーを取得して使うのはもちろんですが、リクエスト数とか、APIキーはプロジェクト単位にあるとか、色々触ると理解が深まりますね。
以上、Google Custom Search APIなど使おうとしている方の参考になれば幸いです。