hamada
bungu****@leo*****
2004年 4月 7日 (水) 12:53:04 JST
こんにちわ。 当方、ずーっとosCommerceの検索エンジン対策ばっかしてきてる(^^;んですが、 対策初期からずーっと気になっていたことがありました。 http://www.google.co.jp/intl/ja/webmasters/guidelines.html > ひとつのページ内に含まれるリンクの数を適当な数に抑えます (100 未満)。 それが↑コレ。 拙作mklist.php http://lists.sourceforge.jp/mailman/archives/tep-j-general/2004-January/001606.html は 「静的に全商品紹介ページ&カテゴリへのリンクを含むHTML(サイトマップ)を 生成するスクリプト」 なんですが、1商品あたり「商品紹介」と「カテゴリ」という2つのリンクを生 成するため、 「mklist.phpで生成されたlist.htmlは、概ね商品数×2+αのリンクを含む」 という宿命的な問題があります。 つまり、商品が2000あった場合はlist.htmlに4000+αの、商品が5000あった場合 はlist.htmlに10000+αのリンクが作り込まれてしまう事になり、これは上記ガ イドラインからあまりにかけ離れています。 ちなみにAll Products Page http://www.oscommerce.com/community/contributions,137 はカテゴリ毎に商品を分類し商品ごとにカテゴリのリンクを作りませんのでリン ク数が若干少ないですが、1ページに全リンクを作り込む→「商品数が多い場合 ページ内リンクが多くなる」と言う意味で同じ問題を抱えていますし、リンクに セッションIDを付加します→クローラー向きではありません。 幸い(当方がアクセスログから独自に解析したところ)いまのGooglebotは上記 ガイドラインよりも遥かに多いリンクが埋め込まれててもなんとかリンクを追い かけてくれてるみたいなんですが、 (Googlebotを主なターゲットにしているハズなのに) ・mklist.phpの出力結果がGoogleのガイドラインに適合していない ・この先Googlebotの仕様がどう変更されるか解らない (→保証されていないのでいきなり追わなくなる可能性も否定出来ない) ことが(もう2年越しで)非常に気になってましたので、なんとかかんとか年度 末を乗り切ったいま、商品登録を増やしても上記ガイドラインに抵触する危険性 の少ないマイナーチェンジ版を作成しておく事にしました。 mklist2.phpは、メーカー毎商品一覧とそれらへのマップHTMLを生成します。 (1メーカーに何百と言う商品を登録してるとこれでもガイドライン値を大幅に 越えちゃいますんで、もう少し工夫が必要だと思います。例えばosCommerceにメー カーを多重登録して各個数を分散するとか) ・/catalog(default.phpと同じトコ)に設置 ・/catalog/listというパーミッション777のフォルダがある ・/catalog/images/pixel_trans.gifという1x1の透明GIF画像がある ・「サーチエンジン対策のURLを使用(開発中)」がTrue ・日本語のみ 動作環境として上記を決め打ちしています。当スクリプトはmklist.phpとほぼ同 じものですので、mklist.phpのドキュメント、およびソース中のコメントも参照 してください。 PHPスクリプトにファイルを作成させようとしてますんで 「ファイルを作る対象フォルダにPHPの動作ユーザ(apache?)による書き込み権限 を付けとかなきゃいけない」 んですが、PHPスクリプトの存在する/catalogに777を付けるのはあまりに危険が 危ないので、一段下に/catalog/listというフォルダを掘りました。 /catalog/listに生成されるのは ・メーカー毎商品一覧list*****.html (*****はmanufacturers_idを5桁数値にしたもの) ・上記list*****.htmlへのリンク集list.html という2種類のHTMLです。桁数を5桁取ってますんで、たぶん99999メーカーま で動作すると思います。試してはいませんけど(^_^;) mklist2.phpはmklist.phpと併用する事を前提にしています。含まれるキーワー ドが多いため(mklist.phpで生成された巨大な)list.html自体がヒットする事 も多い→ctrl+F検索が効く単一ファイルにはそれなりの価値があるので。 mklist2.phpは、mklist.phpよりも「クローラー寄り」です。小さいファイル多 数に情報が分散して見通しが悪くなるので、人間が読むにはあまり向きません。 人間用にはmklist.phpのほうが向いてます。 mklist2.phpと併用する場合は、mklist.phpの上のほうにでも fwrite($fp,"<A href=\"list/list.html\">取扱メーカー毎商品一覧</A><br><br>" ."\n"); ↑こんな行を足しておいてください。既にlist.htmlが十分に巨大な場合は、ク ローラーがリンクを追いきれない可能性も否定出来ないので http://www.google.co.jp/intl/ja/addurl.html ↑こちらとかで/catalog/list/list.htmlに相当するURLを手動登録しておく方が いいかもしれません。 php /var/www/html/catalog/mklist2.php > /dev/null 2>&1 cronで自動処理する場合は↑こんな感じになると思います。 アブナイのでファイルを削除する処理は実装してません。従って、メーカーを削 除した場合はlink*****.htmがそのままサーバに残ります→/list内のファイルは 定期的に手で削除して貰う必要があります。 (osCommerceでメーカーを削除しない限りは大丈夫で、ずっと同じファイルに上 書きされ続けるハズです。また、メーカー削除して放置しても「更新されない孤 立ファイル」が出来ちゃうだけではあります) はまだ mklist2.php ------------------------------------ <?php require('includes/application_top.php'); //メーカー毎一覧へのリンク集list/list.htmlを生成 $fp=fopen("list/list.html", "w") or die("ファイルのオープンに失敗しました"); fwrite($fp,"<!doctype html public \"-//W3C//DTD HTML 4.01 Transitional//EN\">" ."\n"); fwrite($fp,"<html " . HTML_PARAMS . ">" ."\n"); fwrite($fp,"<head>" ."\n"); fwrite($fp,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" . CHARSET . "\">" ."\n"); //ロボットに一覧表をキャッシュさせたい場合はコメントアウト fwrite($fp,"<META NAME=\"ROBOTS\" CONTENT=\"NOARCHIVE\">" ."\n"); fwrite($fp,"<style TYPE=\"text/css\">" ."\n"); fwrite($fp,"<!--" ."\n"); fwrite($fp,"BODY { color: #444455;" ."\n"); fwrite($fp," background-color : #fafaff;}" ."\n"); fwrite($fp,"a:hover { color: #FF0000;" ."\n"); fwrite($fp," text-decoration: underline;}" ."\n"); fwrite($fp,"a:link { color: #3333ff;" ."\n"); fwrite($fp," text-decoration: none;}" ."\n"); fwrite($fp,"-->" ."\n"); fwrite($fp,"</style>" ."\n"); fwrite($fp,"<title>" . TITLE . " - " . $row['manufacturers_name'] . " 取扱いメーカー一覧 " . "</title>" ."\n"); fwrite($fp,"</head>" ."\n"); fwrite($fp,"" ."\n"); fwrite($fp,"<body leftmargin=\"0\" topmargin=\"0\" marginwidth=\"0\" marginheight=\"0\">" ."\n"); fwrite($fp,"<BLOCKQUOTE>" ."\n"); fwrite($fp,"<br>" ."\n"); fwrite($fp,"<A href=\"../list.html\">全商品一覧に戻る</A> | <A href=\"../default.php\">ショップに戻る</A><br><br>" ."\n"); $result = tep_db_query("SELECT manufacturers_id, manufacturers_name FROM manufacturers ORDER BY manufacturers_name"); //登録全メーカーを取得 $num_rows = tep_db_num_rows($result); //全メーカー数を取得 fwrite($fp, "<table width=\"640\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\" bgcolor=\"#eeeeee\"><tbody>\n"); fwrite($fp,"<tr bgcolor=\"#dddddd\"><b>" . TITLE . " 取扱いメーカー一覧</b> [" . $num_rows . "]</tr>" ."\n"); fwrite($fp,"<tr>" ."\n"); $i = 0; //列数カウンタをリセット while($row = tep_db_fetch_array($result)) { //list*****.html形式でファイル名を生成 //manufacturers_idの左に0足して5桁に整形してます $fname = "list" . str_pad($row['manufacturers_id'],5,"0",STR_PAD_LEFT) . ".html"; $products = tep_db_query("SELECT manufacturers_id FROM products WHERE manufacturers_id=" . $row['manufacturers_id'] ); $num_prod = tep_db_num_rows($products); //メーカー毎の商品数 fwrite($fp, "<td><a href=\""); fwrite($fp, $fname); fwrite($fp, "\">"); fwrite($fp, $row['manufacturers_name']); fwrite($fp, "</a>"); fwrite($fp, "<FONT size=\"1\"> [" . $num_prod . "]</font>"); //下にメーカー一覧の列数をセット(デフォルトは3列) if($i+1 >= 3) { fwrite($fp, "</td>\n</tr>\n<tr>\n"); $i = 0; }else { fwrite($fp, "</td>\n"); $i++; } } fwrite($fp, "</tr></tbody></table>\n<br>\n"); fwrite($fp,"<A href=\"../list.html\">全商品一覧に戻る</A> | <A href=\"../default.php\">ショップに戻る</A><br><br>" ."\n"); fwrite($fp,"</BLOCKQUOTE>" ."\n"); fwrite($fp,"<br>" ."\n"); fwrite($fp,"</body>" ."\n"); fwrite($fp,"</html>" ."\n"); fclose($fp); //ファイルをクローズ //list/list.htmlの作成ここまで //ここからlist/list*****.htmlの作成 $result = tep_db_query("SELECT manufacturers_id, manufacturers_name FROM manufacturers ORDER BY manufacturers_name"); //登録全メーカーを取得 while($row = tep_db_fetch_array($result)) { //ファイル名を生成 $fname = "list/list" . str_pad($row['manufacturers_id'],5,"0",STR_PAD_LEFT) . ".html"; $fp=fopen($fname, "w") or die("ファイルのオープンに失敗しました"); fwrite($fp,"<!doctype html public \"-//W3C//DTD HTML 4.01 Transitional//EN\">" ."\n"); fwrite($fp,"<html " . HTML_PARAMS . ">" ."\n"); fwrite($fp,"<head>" ."\n"); fwrite($fp,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" . CHARSET . "\">" ."\n"); //ロボットに一覧表をキャッシュさせたい場合はコメントアウト fwrite($fp,"<META NAME=\"ROBOTS\" CONTENT=\"NOARCHIVE\">" ."\n"); fwrite($fp,"<style TYPE=\"text/css\">" ."\n"); fwrite($fp,"<!--" ."\n"); fwrite($fp,"BODY { color: #444455;" ."\n"); fwrite($fp," background-color : #fafaff;}" ."\n"); fwrite($fp,"a:hover { color: #FF0000;" ."\n"); fwrite($fp," text-decoration: underline;}" ."\n"); fwrite($fp,"a:link { color: #3333ff;" ."\n"); fwrite($fp," text-decoration: none;}" ."\n"); fwrite($fp,"-->" ."\n"); fwrite($fp,"</style>" ."\n"); fwrite($fp,"<title>" . TITLE . " - " . $row['manufacturers_name'] . " 全商品一覧 " . "</title>" ."\n"); fwrite($fp,"</head>" ."\n"); fwrite($fp,"" ."\n"); fwrite($fp,"<body leftmargin=\"0\" topmargin=\"0\" marginwidth=\"0\" marginheight=\"0\">" ."\n"); fwrite($fp,"<br>" ."\n"); $redundancy = "◆"; //ジャンルを重複して登録された商品に付ける接頭記号 //ここからメーカー毎商品の一覧表作成。 //leftmargin="0"なので<blockquote>ではさむ fwrite($fp,"<BLOCKQUOTE>" ."\n"); fwrite($fp,"<A href=\"list.html\">取扱いメーカー一覧に戻る</A> |<A href=\"../list.html\">全商品一覧に戻る</A> | <A href=\"../default.php\">ショップに戻る</A><br><br>" ."\n"); fwrite($fp,"品名の先頭に" . $redundancy . "のついた商品は複数カテゴリーに(重複)登録されている商品です<br>" ."\n<br>\n"); //メーカー毎の全商品を取得 $products = tep_db_query("SELECT p.products_id, d.products_name, p.products_model, t.categories_id, c.categories_name, p.products_status FROM products p, products_description d, products_to_categories t, categories_description c WHERE p.manufacturers_id=" . $row['manufacturers_id'] . " and p.products_id=d.products_id and p.products_id=t.products_id and t.categories_id=c.categories_id ORDER BY c.categories_name , p.products_model"); $num_prod = tep_db_num_rows($products); //メーカー毎の商品数 //表の色設定 $bgcolor = "#fafaff"; $bdcolor = "#bbbbbb"; $thcolor = "#eeeeee"; fwrite($fp,"<a href=../default.php/manufacturers_id/" . $row['manufacturers_id'] . "><b>" . $row['manufacturers_name'] . "</b></a> [" . $num_prod . "]<br>" ."\n"); fwrite($fp,"<table bgcolor=\"" . $bgcolor . "\" border=\"1\" cellspacing=\"0\" cellpadding=\"1\" bordercolor=\"" . $bdcolor . "\">" ."\n"); fwrite($fp,"<tr><img height=\"1\" width=\"640\" src=\"images/pixel_trans.gif\"></tr>" ."\n"); fwrite($fp,"<tr bgcolor=\"" . $thcolor . "\"><th>品名</th><th>品番</th><th>カテゴリー</th></tr>" ."\n"); //ここから表の中身作成 while ($prod = tep_db_fetch_array($products)) { $p_path = tep_get_product_path($prod['products_id']); //商品のカテゴリーパス。重複登録されてるとnullが返る if ($prod['products_status'] == 0) //商品がオフ。 if ($p_path == "") //かつ重複登録商品 fwrite($fp,"<tr><td>" . $redundancy . $prod['products_id'] . "</td><td>" . $prod['products_model'] . "</td><td><a href=\"../default.php/cPath/" . $prod['categories_id'] . "\">" . $prod['categories_name'] . "</a></td></tr>" ."\n"); else //重複登録商品ではない fwrite($fp,"<tr><td>" . $prod['products_name'] . "</td><td>" . $prod['products_model'] . "</td><td><a href=\"../default.php/cPath/" . $p_path . "\">" . $prod['categories_name'] . "</a></td></tr>" ."\n"); //商品がオフでない。 elseif ($p_path == "") //重複登録商品はパスが取れない→単純パスで出力 fwrite($fp,"<tr><td>" . $redundancy . "<a href=\"../product_info.php/products_id/". $prod['products_id'] ."\">" . $prod['products_name'] . "</a></td><td>" . $prod['products_model'] . "</td><td><a href=\"../default.php/cPath/" . $prod['categories_id'] . "\">" . $prod['categories_name'] . "</a></td></tr>" ."\n"); else //それ以外。全部出力 fwrite($fp,"<tr><td><a href=\"../product_info.php/cPath/" . $p_path . "/products_id/" . $prod['products_id'] . "\">" . $prod['products_name'] . "</a></td><td>" . $prod['products_model'] . "</td><td><a href=\"../default.php/cPath/" . $p_path . "\">" . $prod['categories_name'] . "</a></td></tr>" ."\n"); } fwrite($fp,"</table>" ."\n"); fwrite($fp,"<br>" ."\n"); fwrite($fp,"<A href=\"list.html\">取扱いメーカー一覧に戻る</A> |<A href=\"../list.html\">全商品一覧に戻る</A> | <A href=\"../default.php\">ショップに戻る</A><br><br>" ."\n"); fwrite($fp,"" ."\n"); fwrite($fp,"" ."\n"); fwrite($fp,"</BLOCKQUOTE>" ."\n"); fwrite($fp,"<br>" ."\n"); fwrite($fp,"</body>" ."\n"); fwrite($fp,"</html>" ."\n"); fclose($fp); //ファイルをクローズ } echo("Update works Completed!" . "\n"); ?>