と~く2ちゃんねる
最終更新日: 2003/09/03Samba24
2ちゃんねるとお話するための方法をまとめたメモです。
※このページはコミュニケーションサイトではありません!
目次
2ちゃんねるの仕様は日々変わっていくので、ここに書いてある情報は古いかもしれません。
もし、間違え・仕様変更などがあれば掲示板の方へ書き込んで教えてくれると非常に助かります。
最新情報
Samba24という規制が始まった模様。(8月下旬~)
基本
- 2chの漢字コードはShift-JISである
- 接続先ポート番号はもちろんTCPの80番になります
- スレッドのURLが
http://news2.2ch.net/test/read.cgi/newsplus/1000000000/ならば- ホスト名: news2.2ch.net
- 板キー: newsplus
- スレキー: 1000000000
基本はこの3つだけです。簡単ですね?
では、どんどんいってみよー。
読み
スレッド一覧の取得
- subject.txtの場所
- /板キー/subject.txt
- subject.txtのフォーマット
- スレキー.dat<>スレタイトル (総レス数)\n
- http要求ヘッダ例
GET /newsplus/subject.txt HTTP/1.0
Accept-Encoding: gzip
Host: news2.2ch.net
User-Agent: Monazilla/1.00
Connection: close
要求が成功すれば200 HTTP_OKが返ってくる。
この例の場合、要求ヘッダでgzip圧縮を受け入れるようにしているため、応答ヘッダで圧縮されているか確認して、必要ならば解凍しなければいけない。
圧縮されたかどうか確認するには、応答ヘッダContent-Encodingにgzipがあるか調べる。
2chでは、転送量問題が発生した時から、データをgzip圧縮して返すことを推奨(必須?)している。
圧縮要求しなければデータを取得できない、なんてサーバもあったような気が。。
ユーザエージェントは、とりあえずモナジラと名乗っておきます。
subject.txtが更新されていなかったらデータを取得しないように、If-Modified-Sinceを付けて要求するのも、無駄な負荷を減らすポイントです。
DATの取得
- DATの場所
- /板キー/dat/スレキー.dat
- DATのフォーマット
- 名前<>メール欄<>日付、ID<>本文<>スレタイトル(1行目のみ存在する)\n
- http要求ヘッダ例
GET /newsplus/dat/1000000000.dat HTTP/1.0
Accept-Encoding: gzip
Host: news2.2ch.net
User-Agent: Monazilla/1.00
Connection: close
要求が成功すれば200 HTTP_OKが返ってくる
見つからなければ302 HTTP_MOVED_TEMPORIALYや404 HTTP_NOT_FOUNDなどが返ってくる
DAT差分を取得
要求ヘッダに次の項目を追加する
If-Modified-Since: リモートDATの最終更新時刻(値は応答ヘッダのLast-Modifiedを調べる)
Range: bytes=ローカルDATのファイルサイズ-
ファイルサイズの単位はバイト。ローカルdatは2chのdatと完全に同じであることが前提条件。
Windowsデフォルトの改行は\r\n、2chデフォルトの改行は\nなので、1バイト×レス数のファイルサイズ不一致、という罠に嵌りやすいので注意。
ローカルdatが2chと違う仕様なら、受信したデータのサイズ(解凍後)を累積記録などして、それを使用する。
If-Modified-SinceとDateヘッダの値は、RFC1123形式で表される時刻。例えば、Fri, 30 Mar 2001 22:35:45 +0900
DATが更新されていれば206 HTTP_PARTIAL_CONTENTが返ってきて、差分データを取得できる。
更新(新着)なしならば304 HTTP_NOT_MODIFIEDが返ってくる
あぼーんがあった場合、ファイルサイズ不一致により、データが取得できません。(ローカルDAT>リモートDAT)
返ってくるステータスは416 HTTP_RANGE_NOT_SATISFIABLEになります。
参考までに、あぼーんをより確実に検出するために、次のような工夫をして差分取得しているブラウザもあるようです。
If-Modified-SinceにリモートDATの更新時刻、rangeに取得済みDATのサイズマイナス1を指定して要求する。
- 新着なしなら304 HTTP_NOT_MODIFIEDが返ってきて、データは送信されない
- 新着あり、つまりContent-lengthが2以上の場合は、受信データの先頭を確認して\nだったら正常、\n以外だったらあぼーん。
- 新着なし+あぼーんがあった時は416。(ローカルDAT>リモートDAT)
DAT落ちを取得
2chでは次のようにスレッドが変遷します
- スレッドが立てられる
- ライブスレッド
- 一定期間書き込みがない場合や1000を超えた場合、DAT落ちする
- 過去ログ化
DAT落ちのスレは、IDを購入してログインしないと閲覧できない仕組みになっています。
ログイン方法はログインの項目をお読みください。
ログインしてSESSION-ID(sid)を受け取れば、後は通常のDATと同じように取得します。
詳しく知るには、これもログインの項目を見てください。
過去ログを取得
- 過去ログの場所
- スレキーが10桁の場合 /板キー/kako/スレキーの上位4桁/スレキーの上位5桁/スレキー.dat.gz
- スレキーが9桁の場合 /板キー/kako/スレキーの上位3桁/スレキー.dat.gz
dat.gzは既にgzip圧縮されています。解凍すれば通常のDATファイルになります。
ブラウザで見るには拡張子dat.gzをhtmlにすればOKです。
dat.gzが見つからない場合は、拡張子をdatにして探してみてください。過去ログが存在するなら、dat.gzかdatのどちらかがあるはずです。
過去ログ倉庫にもsubject.txtが存在する場合があります。
場所は/板キー/kako/スレキーの上位4桁/スレキーの上位5桁/subject.txtになります。
しかし、存在しない場合がほとんどですが。。
基本は以上の通りですが、まだ他にもパターンがあるようです。
過去ログ倉庫を覗いてみると、次のような仕様の過去ログもあります。
- レガシー仕様 www(tako)、www(kitanet)、piza(log)、piza(log2) mentai(mukashi)
- DATファイルの場所は/takoまたはkitanetまたはlogまたはlog2またはmukashi/板キー/kako/スレキーの上位3桁/スレキー.dat
DAT書式は区切り文字がコンマの古いタイプで無圧縮。ブラウザで見るには拡張子datをhtmlに - ログイン仕様 1999、pyon、kitanet、jbbs、2002a
- 筆者はIDを持ってないので(以下略)。
ログイン仕様サーバにはsubject.txtが存在するようで、場所は/板キー/subject.txtになります。
当然ですが、DATはブラウザから見れません。
ほかにも仕様があるみたいだけど、全てを把握するのは難しい。。とりあえず、見つけた仕様を列挙しときます。
/板キー/log/yyyymmdd/スレキー.dat(レガシー仕様) http://tako.2ch.net/bike/log/
書き
レスを書き込む
- POSTする場所
- /test/bbs.cgi
- http要求例
POST /test/bbs.cgi HTTP/1.0
Host: news2.2ch.net
Content-length: ポストするデータのサイズ(バイト)
Referer: http://news2.2ch.net/newsplus/
User-Agent: Monazilla/1.00
Cookie: NAME=名前; MAIL=メール; SPID(PON)=値; expires=有効期限; path=/
Connection: close
bbs=newsplus&key=1000000000&time=1&submit=書き込む&FROM=名前&mail=メール&MESSAGE=本文- ポストするデータの内容
-
- bbs
- 板キー
- key
- スレキー
- time
- 2ch側の書き込みフォームが生成された時刻。time関数の戻り値である。
たいがいの2chブラウザはローカルで時刻を生成していたが、規制によって未来からの書き込みが禁止になった。 ローカルの時計が狂っていると永久に書き込めないのである。
そこで現在は、datを取得した時の応答ヘッダにあるDateヘッダの値から逆算するなどの工夫が取られている。
しかし、2ch側では有効期限をチェックしていない、ちょっとアレな仕様のため、適当に大昔の時刻を入れても大丈夫なのである。 - submit
- 書き込みボタンのキャプション。通常は”書き込む”。文字列はURLエスケープしておきましょう。
これがないと「SJISで書いてね」とか怒られる。初めて2chとお話しすると、まずこの罠に嵌ります。 - FROM
- 名前。URLエスケープしておく必要があります。FROMは大文字であることに注意!
URLエスケープ
半角空白→「+」
「エスケープ」→「%a5%a8%a5%b9%a5%b1%a1%bc%a5%d7」
- メール。URLエスケープしておく必要があります。
- MESSAGE
- 本文。URLエスケープしておく必要があります。MESSAGEは大文字です。
- sid
- セッションID。ログインすると発行されるあれです。ログインしていないなら不要。
もし付与するなら、これもURLエスケープしておきます。
- クッキーについて
-
- NAME
- 名前。URLエスケープしておく必要があります。
- メール。URLエスケープしておく必要があります。
- SPIDまたはPON
- 書き込み時に発行される、クッキーのSPID値またはPON値。
値と名前を知るには、POSTすると返ってくる応答ヘッダのSet-Cookieヘッダの中身を調べてください。
ホスト毎に発行され、IPアドレスや日付が変わると値が変わります。これがないと、クッキー確認画面より先へ進めません。
これもURLエスケープしておきます。SPID(PON)はローカルに保存して再利用するようにします。たとえ値が不正でも、また発行されますから。
- expires(有効期限)
- 有効期限はチェックしていないようです。PONがあるし。
しかし、応答ヘッダのクッキーを見て、一応付けておいた方がいいでしょう。
- 書き込み確認
- いくつかの例を挙げてみます。
いろいろパターンがあって難しいのが少々ネックになっています。 -
- <title>タグの中身</title>を調べる
-
- 書き込みが成功すると、書きこみましたという文字列が入る
- 書き込みが失敗すると、ERRORという文字列が入る
- サーバの負荷が高く、書き込めない場合は、お茶でもという文字列が入る
- クッキー確認の場合は、書き込み確認という文字列が入る
- 書き込み失敗エラーの内容を知るには、最初にくる<b>タグの中身を調べます。
お茶飲みエラーの場合は次のようなHTMLが表示されます。<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=x-sjis"><TITLE>お茶でも飲みましょう。</TITLE></HEAD>
サーバの負荷が高いので書きこめません。<br>(21.58 : 目標は 5.00 以下)<hr>もちろん、このページをリロードするのも負荷かかります。</BODY></HTML> - 2chタグを調べる
- <html>タグの次にコメントタグ(以下、2chタグ)が入っていることがあります。
-
- 正常に書き込みが終了 <!– 2ch_X:true –>
- 書き込みはしたが注意つき <!– 2ch_X:false –>
- ERROR!のタイトル <!– 2ch_X:error –>
- スレ立てなど書き込み別画面 <!– 2ch_X:check –>
- クッキー確認画面 <!– 2ch_X:cookie –>
- タイトルタグと2chタグの両者を調べて、どちらかがtrueならば~するという処理にするのが、現時点ではベストな方法かと思われます。
なお、管理側の通達により、確認画面を自動処理してスルーすることは緩やかに禁止されています。だから、かちゅ使ってるとクッキー確認のダイアログがしょっちゅうでるんですよね。
スレッドを立てる
スレッドを立てる動作は、レスを書き込む動作とほとんど共通であり、テストするのも困難なので、適当に説明します。
- POSTする場所
- /test/bbs.cgi
- /test/subbbs.cgi
- ポストするデータの内容(レス書き込みと違う点)
- subjectにスレタイトル
- keyは不要
- bbs.cgiに投げる場合、submitは「新規スレッド作成」
- subbbs.cgiに投げる場合、submitは「全責任を負うことを承諾して書き込む」
- クッキー
- レス書き込みの場合と同じです
さてスレッドを立てる方法ですが、まずbbs.cgiに投げてみます。
これだけでスレが立っちゃう板もあります。この場合のスレ立て成否確認方法は、レス書き込み確認と同じになります。
中には、スレ立てにワンクッション置く板もあり、この場合は次のように表示されます。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=x-sjis">
<TITLE>板名@2ch掲示板</TITLE>
</HEAD><body bgcolor="#FFFFFF">
<font size=+1 color=#FF0000>書き込み確認。</font><br><br>
書き込みに関して様々なログ情報が記録されています。<br>
公序良俗に反したり、他人に迷惑をかける書き込みは控えて下さい<br>
\t<form method=POST action="../test/subbbs.cgi">
(以下略)
この場合、subbbs.cgiにもう1回投げる必要があります。
subbbs.cgiに投げた時のスレ立て成否確認方法は、失敗ならレス書き込み確認と同じになりますが、成功なら(以下作成中)
面倒。。
その他
板一覧
2chの板一覧を調べるには、2chで使用しているbbsmenu.htmlから解析します。
- カテゴリの書式
- 行先頭から<BR><BR><B>カテゴリ名</B>~略~行末
- 板の書式
- 行先頭から<A HREF=http://ホスト名/板キー/>板名</A>~略~行末
ホスト名が*.2ch.net or *.bbspink.comにマッチしたモノだけを抜き出せば、必要な板が揃うでしょう(www.2ch.netは除く)
bbspinkは2chと同じ仕様なので含むことにしますが、まちBBSは2chと仕様が大きく異なるため除外することにします。
bbsmenu.htmlは適当ぽい書式でちょっと怖いですが、実績があるのでまず大丈夫でしょう。
ここで1つ問題提起。板キー重複の問題です。
2chでは板キーが重複しないように努力しているみたいですが/*ちょっと間抜けなので*/板キーが重複した前歴があるし、
将来に渡って重複しない保証はありません。
現在では板キーの重複は皆無ですが、板キーで板を判断する場合は、常にこの問題があることを頭に入れておきましょう。
ユーザエージェント
DATを取得する際は、User-AgentがMonazillaでなければ基本的に取得できません。
なので、2chブラウザを作った場合には、Monazillaを名乗る必要があります。
User-Agentの書式は「Monazilla/1.00 ブラウザ名/バージョン番号」となります。
Monazillaを名乗るには、運営側の許可は必要なく、誰でも自由に行えるようです。
ログイン
kage作者さんのサイトにログインについての詳細があります。そちらをお読みください。
筆者はIDを持っていないので説明できません。。
板移転
subject.txtが見つからない場合は、板が移転したと判断しても大丈夫でしょう。
板が移転した場合、/板のキー/のHTMLに移転先が書いてあるので、それを調べるのがよいかと。
でも100%確実ではないので、細心の注意が必要です。移転先のページがまた移転先のお知らせだったりすることもあるので。。
<title>タグの中身が2chbbs..だったら確実に移転です。移転先は最初にくる<a>タグの中に書いてあります。
<a href=”http://移転先.2ch.net/板キー/”>GO !</a>
巡回
HEADメソッドとIf-Modified-Sinceヘッダを利用して、DATが更新されているかどうかだけを調べるのがベストだと思いますが、どうなんでしょう。
えいやーとGETメソッドを投げまくると、夜勤さんが卒倒しそうだし、ここは控えめに行きましょう。
ちなみにHEADを投げると、更新されていれば200 HTTP_OK、更新されていなければ304 HTTP_NOT_MODIFIEDが返ってきます。
これまでの経験によると、18時~19時、20時~22時は特に混雑する時間帯です。
この負荷ピーク時の巡回を抑えれば、サーバに優しくなるでしょう。
2chのURLオプション
簡単に2chのURLとオプションを説明します。
http://ホスト名/test/read.cgi/板キー/スレキー/オプション (PATH_INFO形式)
http://ホスト名/test/read.cgi?bbs=板キー&key=スレキーオプション (QUERY_STRING形式)
| PATH_INFO形式のオプション | 説明 | QUERY_STRING形式のオプション |
|---|---|---|
| 数字 | その番号のレスだけを表示する(1は表示されない) | &st=数字&to=数字 |
| 数字A-数字B | 数字Aから数字Bまでのレスを表示する(1は表示される) | &st=数字A&to=数字B |
| 数字- | 数字以降のレスを全て表示する(1は表示される) | &st=数字 |
| -数字 | 1から数字までのレスを全て表示する | &to=数字 |
| l数字 | 最新数字件のレスを表示する(1は表示される) | &ls=数字 |
| n | 1を除外する | &nofirst=true |
| i | 携帯用(r.iができたから過去の遺物化に) | &imode=true |
複数オプションにも対応してます。例えば、1を除外した最新10レスを携帯用に表示したい場合はl10niになります。
昔はQUERY_STRING形式のURLが使われてましたが、現在ではPATH_INFO形式が主に使われています。
QUERY_STRING形式でも動きますが、かっこわるいしレガシーなのでPATH_INFO形式を使いましょう。
参考までに、携帯用のr.i(read.cgiの短縮形)というのもあります。
http://ホスト名/test/r.i/板キー/スレキー/
トリップとIDの算出方法
サンプルプログラムをどうぞ。(Perl)
トリップは書き込む前に知ることができる。
IDは書き込むまで知ることができない。(IDからIPを割るのは不可能です)
head.txt
板のローカルルールが書かれたファイル。HTMLタグで書かれています。
head.txtには<html>タグや<body>タグがないので、各ブラウザでhead.txtを表示するには適当にタグを付けてあげましょう。
/板キー/head.txtにあります。
UAにMonazillaを付けてgetしないと、取得できない板もあるようです。
SETTING.TXT
板の設定が書かれたファイル。
/板キー/SETTING.TXTにあります。
UAにMonazillaを付けてgetしないと、取得できない板もあるようです。
設定の詳細は2ちゃんねる初心者のためのページで調べることができます。
/_service/
サーバの負荷率や、サーバに存在する板一覧ファイルなどが置いてあるディレクトリ。
/_service/にあります。
サーバ負荷監視所さんはこれを利用しているようですね。
monazilla.org
monazilla.orgは2ちゃんねるブラウザを開発するプログラマの集まりです。
もし、2chブラウザを作ろうとしているならば、monazillaに参加するといいかもしれません。
また、monazillaには資料類も豊富にあるので、ブラウザ開発の参考になるでしょう。
筆者には2chブラウザを作る技術もなければ気力もないので...
付録 – rawモード
read.cgiにはrawモードというオプションがあります。
rawモードを使用すると、目的のレスだけをDAT仕様で取得することができます。
便利といえば便利ですが、通常の2chブラウザでrawモードを使用する必要性はほとんどないでしょう。
read.cgiを呼び出すため、dat取得よりもサーバに対し負荷がかかりますし。。
rawモードの使用例
subject.txtを全て取得する
http://ホスト名/test/read.cgi/板キー/?raw=0.0
subject.txtの最新50件を取得する
http://ホスト名/test/read.cgi/板キー/?raw=0.0&ls=50
subject.txtの30~60件を取得する
http://ホスト名/test/read.cgi/板キー/?raw=0.0&st=30&to=60
datを全て取得する
http://ホスト名/test/read.cgi/板キー/スレキー/?raw=0.0
datの10~20件までを取得する
http://ホスト名/test/read.cgi/板キー/スレキー/?raw=0.0&st=10&to=20
datの1を取得する
http://ホスト名/test/read.cgi/板キー/スレキー/?raw=0.0&st=1&to=1
datの30件目以降を取得する
http://ホスト名/test/read.cgi/板キー/スレキー/?raw=0.0&st=30
rawモードのオプションはQUERY_STRING形式のオプションとほとんど同じですが、目的のレスだけが出力される点で少々異なります。
rawモードのオプションには標準でnオプション(1を除外する)が付いていると考えれば、QUERY_STRING形式のオプションと同じになります。
rawモードの出力
rawモードで呼び出すには、要求ヘッダにAccept-Encoding: gzipが必要であり、出力はgzip圧縮されて返ってきます。
それと、User-Agentがモナジラだと弾かれたような気が。
最近は、Accept-Encodingがなくても大丈夫なようです。転送量よりCPU、I/O負荷の方が問題になっているからだと思われますが。
rawモードの出力は、1行目にステータス、2行目以降から要求されたデータになります。
ステータス行の例を以下に示します。
+OK 39324/512K…全取得+PARTIAL 2752/512K Range:1914-4665/39324 Res:10-20/194…範囲指定-ERR そんな板orスレッドないです。…エラー
範囲指定を例に書式を説明します。(\tはタブ、\nは改行)
ステータス\t出力バイト/512K\tRange:開始バイト-終了バイト/スレの総バイト\tRes:開始レス番号-終了レス番号/総レス数\n