unoh.github.com

Amazonの商品個別ページのURLからASINを取得する

Mon Mar 24 20:08:18 -0700 2008

isogawaです。

題名のままのコードを書く用事があったので、できたものを晒します。とはいえ、ググれば多くの先達が既にさまざまなコードを書いておられ、目新しいものではないんですが。ついでなんで、大昔の「ISBN=~」を含めて、自分の知ってるURLのパターンを洗いなおしてみました(それでも、まだ他のパターンがありそうな気がしますが…)。

例えば、「The Elements of Style」という書籍の個別商品URLとして思いつくものには、以下のようなパターンがあります(細かいバリエーションは適宜省略)。

スキームがhttpの場合とhttpsの場合、ホストの「www.」の有無、及び日本のサイトについては「.co.jp」と「.jp」の両ドメイン名で、表示内容に違いは見られないようです。

なお、ASIN以降スラッシュに続けて、アソシエイトIDを初めとした各種パラメータが付与されますが、必ずASIN以降であるようなので、ここでは無視します。

というわけでコードですが。以下はJavaScriptですが、やってることはパスをバラして正規表現で評価してるだけなので、他の言語にもサクっと置き換えられるかなと。

/**
 * Retrieves ASIN value from the given Amazon product page URL.
 *
 * @param  string   url   Amazon product page URL
 * @return string         ASIN value contained in the given URL
 *                        Returns empty string if no match
 */
function getAsinFromUrl(url) {
  if (!/^https?:\/\/(?:www\.)?amazon\.(?:com|ca|co\.uk|de|co\.jp|jp|fr|cn)\/(.+)$/.test(url)) {
    return '';
  }
  var path = RegExp.$1;
  var paths = path.split('/');
  if (paths[0].toLowerCase() == 'exec') {
    paths = paths.slice(1);
  }
  if (paths.length <= 1 || paths[1] == '') {
    return '';
  }
  switch (paths[0]) {
  case 'OBIDOS':
  case 'obidos':
  case 'o':
    /**
     * May match the following examples:
     * - http://www.amazon.co.jp/exec/obidos/ASIN/020530902X
     * - http://www.amazon.co.jp/o/ASIN/020530902X
     */
    if (paths[1].toLowerCase() == 'asin' && paths.length >= 3 && paths[2] != '') {
      return paths[2];
    /**
     * May match the following examples:
     * - http://www.amazon.co.jp/exec/obidos/ISBN=020530902X
     * - http://www.amazon.co.jp/exec/obidos/ISBN%3D020530902X
     * - http://www.amazon.co.jp/o/ISBN=020530902X
     */
    } else if (/^isbn(?:=|%3d)(.+)$/i.test(paths[1])) {
      return RegExp.$1;
    /**
     * May match the following examples:
     * - http://www.amazon.co.jp/exec/obidos/tg/detail/-/020530902X
     * - http://www.amazon.co.jp/exec/obidos/tg/detail/-/Elements-Style/020530902X
     * - http://www.amazon.co.jp/o/tg/detail/-/020530902X
     * - http://www.amazon.co.jp/o/tg/detail/-/Elements-Style/020530902X
     */
    } else if (paths[1].toLowerCase() == 'tg'
      && paths.length >= 5
      && paths[2].toLowerCase() == 'detail'
      && paths[3] == '-') {
      if (/^[0-9a-zA-Z]{10}$/.test(paths[4])) {
        return paths[4];
      } else if (paths.length >= 6 && paths[5] != '') {
        return paths[5];
      }
    }
    break;
  /**
   * May match the following examples:
   * - http://www.amazon.co.jp/gp/product/020530902X
   * - http://www.amazon.co.jp/gp/product/product-description/020530902X
   */
  case 'gp':
    if (/^gp\/product(?:\/product-description)?\/([0-9a-zA-Z]{10})/.test(path)) {
      return RegExp.$1;
    }
    break;
  /**
   * May match the following examples:
   * - http://www.amazon.co.jp/dp/020530902X
   * - http://www.amazon.co.jp/Elements-Style/dp/020530902X
   * - http://www.amazon.co.jp/Elements-Style/dp/product-description/020530902X
   */
  default:
    if (/\/?dp(?:\/product-description)?\/([0-9a-zA-Z]{10})/.test(path)) {
      return RegExp.$1;
    }
  }
  return '';
}

なお、個別商品ページを表示した状態でブックマークレットとかでASINを拾うとか、ページのDOMが利用できる状況なら、URLをいぢくるよりdocument.getElementById('ASIN')のほうが確実なのは、これもググればさまざまなに述べられている通りなので、念のため。