2ちゃんねるとお話するための方法をまとめたメモです。
※このページはコミュニケーションサイトではありません!
2ちゃんねるの仕様は日々変わっていくので、ここに書いてある情報は古いかもしれません。
もし、間違え・仕様変更などがあれば掲示板の方へ書き込んで教えてくれると非常に助かります。
Samba24という規制が始まった模様。(8月下旬〜)
http://news2.2ch.net/test/read.cgi/newsplus/1000000000/
ならば
基本はこの3つだけです。簡単ですね?
では、どんどんいってみよー。
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を付けて要求するのも、無駄な負荷を減らすポイントです。
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などが返ってくる
要求ヘッダに次の項目を追加する
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を指定して要求する。
2chでは次のようにスレッドが変遷します
DAT落ちのスレは、IDを購入してログインしないと閲覧できない仕組みになっています。
ログイン方法はログインの項目をお読みください。
ログインしてSESSION-ID(sid)を受け取れば、後は通常のDATと同じように取得します。
詳しく知るには、これもログインの項目を見てください。
dat.gzは既にgzip圧縮されています。解凍すれば通常のDATファイルになります。
ブラウザで見るには拡張子dat.gzをhtmlにすればOKです。
dat.gzが見つからない場合は、拡張子をdatにして探してみてください。過去ログが存在するなら、dat.gzかdatのどちらかがあるはずです。
過去ログ倉庫にもsubject.txtが存在する場合があります。
場所は/板キー/kako/スレキーの上位4桁/スレキーの上位5桁/subject.txtになります。
しかし、存在しない場合がほとんどですが。。
基本は以上の通りですが、まだ他にもパターンがあるようです。
過去ログ倉庫を覗いてみると、次のような仕様の過去ログもあります。
ほかにも仕様があるみたいだけど、全てを把握するのは難しい。。とりあえず、見つけた仕様を列挙しときます。
/板キー/log/yyyymmdd/スレキー.dat(レガシー仕様) http://tako.2ch.net/bike/log/
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=本文
URLエスケープ
半角空白→「+」
「エスケープ」→「%a5%a8%a5%b9%a5%b1%a1%bc%a5%d7」
SPID(PON)はローカルに保存して再利用するようにします。たとえ値が不正でも、また発行されますから。
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=x-sjis"><TITLE>お茶でも飲みましょう。</TITLE></HEAD>
サーバの負荷が高いので書きこめません。<br>(21.58 : 目標は 5.00 以下)<hr>もちろん、このページをリロードするのも負荷かかります。</BODY></HTML>
だから、かちゅ使ってるとクッキー確認のダイアログがしょっちゅうでるんですよね。
スレッドを立てる動作は、レスを書き込む動作とほとんど共通であり、テストするのも困難なので、適当に説明します。
さてスレッドを立てる方法ですが、まず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から解析します。
ホスト名が*.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とオプションを説明します。
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/板キー/スレキー/
サンプルプログラムをどうぞ。(Perl)
トリップは書き込む前に知ることができる。
IDは書き込むまで知ることができない。(IDからIPを割るのは不可能です)
板のローカルルールが書かれたファイル。HTMLタグで書かれています。
head.txtには<html>タグや<body>タグがないので、各ブラウザでhead.txtを表示するには適当にタグを付けてあげましょう。
/板キー/head.txtにあります。
UAにMonazillaを付けてgetしないと、取得できない板もあるようです。
板の設定が書かれたファイル。
/板キー/SETTING.TXTにあります。
UAにMonazillaを付けてgetしないと、取得できない板もあるようです。
設定の詳細は2ちゃんねる初心者のためのページで調べることができます。
サーバの負荷率や、サーバに存在する板一覧ファイルなどが置いてあるディレクトリ。
/_service/にあります。
サーバ負荷監視所さんはこれを利用しているようですね。
monazilla.orgは2ちゃんねるブラウザを開発するプログラマの集まりです。
もし、2chブラウザを作ろうとしているならば、monazillaに参加するといいかもしれません。
また、monazillaには資料類も豊富にあるので、ブラウザ開発の参考になるでしょう。
筆者には2chブラウザを作る技術もなければ気力もないので...
read.cgiにはrawモードというオプションがあります。
rawモードを使用すると、目的のレスだけをDAT仕様で取得することができます。
便利といえば便利ですが、通常の2chブラウザでrawモードを使用する必要性はほとんどないでしょう。
read.cgiを呼び出すため、dat取得よりもサーバに対し負荷がかかりますし。。
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モードで呼び出すには、要求ヘッダに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