このブログを検索

2012/12/20

2ちゃんねるでスクレイピングが失敗する

さくらのVPSサーバから、あるサイトにアクセスし、そのWEBサイトの情報の一部を取り出すという事をしている。いわゆる「スクレイピング」である。 

最初はperlで、LWP::Useragentなどを使って、あるサイトの情報を取り、あとは正規表現などを使って試行錯誤しつつ欲しい情報のみを取り出した。 特に難しいことはない。

ところが、同じ事を2ちゃんねるでやってみたら、うまくいかない。やろうとしたのは、ニュース速報の上位のスレッドタイトルを取得することだった。 2ちゃんねるは掲示板のメニューがあってそこに各掲示板のURLが記載されている。そしてその掲示板のURLはかなり頻繁に変更されるので、そのときアクセスできているURLに固定でアクセスせずに、メニューからURLを取得しなければならない。 その、メニューからURLを取得することはできたのだが、そこから取得したURLへアクセスすると、どうしてもHTMLの内容が取得できないのだ。

まずは、「302 Found」というエラーになる。これはリダイレクトされたときに出るもののようで、あるところで

push @{ $ua->requests_redirectable }, 'POST';
をやればいいという情報を見つけたのでやってみたら、今度は「ボボンハウス」のページが表示されてしまう。

同じperlスクリプトをローカルPCで動かしても同じ状況になる。 もちろん、ブラウザやギコナビなどでは問題なくアクセスできている。 昨日はここまでやって、あきらめて寝た。 

そして今日、perlのスクリプトでアクセスしたときと、ブラウザでアクセスしたときのパケットをwiresharkでキャプチャして比較してみた。

すると、GETしているときに、・・・・ と、ここまで書いてuseragentが違うことに気づいた。 perlで書いたものは何も設定しておらず、lwpの初期値が入っている。 これを'Mozilla'に変えたら・・・いけた。

昨日、変えてダメだったような記憶があったんだけどな・・・ ま、いいや。 これだけでいけるようになるということは、2ちゃんねるの「スクリプトキディ」除けかな。

今日はWEBでphpをつかったスクレイピング例を見つけてそれがうまく動いたのでそれをいじっていた。

しかし今度はphpの動作で不可解なところがでてきた。 まず、phpをcgiとして動かすために必要な設定がなんなのか。 いろいろと情報があるのだが、皆条件付でスパっと「ここをこうする!」という情報がない。

これも試行錯誤で試して、なんとかうごいた。 前回はこんなに苦労した記憶はないのに・・・。 さらに、いちおう動いたのだが、出力する内容が全部そのまま出てしまう。 htmlのリンクとかを書いても、そのまま表示されてリンクにならないのだ? なんでだ? 

話は変わるが、正規表現であるパターンにマッチする文字列が複数あり、それをすべて取り出したいときにはどうすればいいのだろう? たとえば、今まさにやりたかったのは、httpでgetしたデータの中にあるリンク(a href) を全部取り出して配列に格納する、というようなケースだ。 パッと思いつかず、サラっと探しても見つからなかったので、a hrefの前で改行してファイルに吐き出し、そのファイルを読んで一行ずつ処理するというメンドクサイことをしている。 こんなことしなくてもできるよね・・・。

2012/12/09

sedで一括置換できない

わけあって、以下のような置換をそこそこたくさんのファイルについて実行しなければならなかった。

%s/\n<br>/<br>/g


viで一個ずつ置換していたのだが、sedでやれば一括でできるだろうとやってみたが、できない。

sed -i -e 's/\\n<br>/<br>/g'


なんでだろう?

まあ、たいした数ではなかったので、一個ずつviで開いて置換をしていった。




2012/12/07

twitterのbotが動かなくなった



以前使っていて特に不満はなかったのだが諸事情により解約したVPSを再度契約した。

レンタルサーバにしようか、VPSにしようか迷ったのだが、480円しか違わないのでお勉強のためも兼ねようと、VPSにした。

twitterのbotを復活させようとしてNet::Twitterを入れようと、いつものようにやったらエラーになった。

[hoge]# perl -MCPAN -e shell
Can't locate CPAN.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .).
BEGIN failed--compilation aborted.


調べるとモジュールのインストールが必要とのことだった。

yum install perl-CPAN


いつもおまじないのように実行していたが、モジュールを使っていたんだね。

さて、前に動かしていたbotが動かない。tweetができない。ascii文字とリテラルならいけるが、ファイルから読み込んだutf8の日本語がtweetできない。

自宅にあるcentosで、同じスクリプトが動いている。

Encodeのバージョンが、動かないVPSの方が新しい。

Centosはともに6.3だが、VPSは64ビット版、家は32ビット。

Perlのバージョンは同じ。

Net::Twitterも同じ。

Encodeのバージョンが違うというのが一番あやしい。下げてみようか・・・

でもそれより、動いているスクリプトがおかしくて、本来よくないやり方なのがたまたま動いていた、という問題な気がする・・・・

Net::Twitter::Liteにしたらうまくいった・・・。

原因は不明。

あー時間を空費した。

その後・・・

今度はblockしているユーザの一覧とその解除をする、OAuthを使うcgiを動かしたらこれも動かない・・・

最近apiの仕様が変わったという話は聞いていたが、そんな問題じゃない感じがする・・・

あれこれやってもどうしてもわからず、access token等を直接書いてblockしているユーザーを表示するスクリプトを動かしてみたら、数十秒かかる。

なんだこれ・・・




2012/11/25

「ブリッジ接続」の使い方

ノートPCに入れたCentOS6.3での無線LANアダプタの利用はあきらめて、とりあえずケーブルでWindows7パソコンにつないで使っていたが、やはりインターネットにつなげないと困る。

じゃあWindows7でルーティングしてみようか・・・でもNATとかしないといけない・・・

と、「ブリッジ接続」を思い出した。

これはたしかXPから追加された機能であるが、使い方がよくわからなかったのだが、まさに私がいま利用しているような場合にぴったりの機能だった。

「ネットワークと共有センター」→「アダプタの設定の変更」で、インターネットに接続しているアダプタと、もう一個のアダプタを両方選択してから右クリックし、「ブリッジ接続」を選択する。

そして私の場合でいえば、ノートPCのインタフェースの設定を、インターネットに接続しているネットワークのアドレスにし、ゲートウェイはWindowsパソコンに設定しているのと同じものをしていすればよい。

こうすると、二つのインタフェースが一つのインターネット接続を共有できる。

こうやって使うのか・・・。




2012/11/24

CentOSで無線LAN

CentOS6.3をdellのノートPCにインストールした。
CGIの試験などをするために。
そのノートPCは普段無線LANで使っているのだが、
CentOSで無線LANを使ったことがないのでできるだろうかと不安になった。
WEBで調べると、使えるようだったがちょっと面倒なようだった。
なんとか、make, make install, insmodまでできて、
iwlist ra0 scan をしてAPの情報も見えた。
ところが、どうしてもDHCPでアドレスが取れない。
固定IPを設定しても、ゲートウェイと通信できない。
SSID、暗号方式、パスワード等が間違っているような動きに見えるのだが、
何度も確認してみたがどうしても接続できない・・・・。

無線LANアダプタは BuffaloのWLI-UC-GNM
lsusbをすると、Ralink RT8070 となっている。
ドライバは http://www.ralinktech.com からダウンロードできる。
無線LANルータは Emobileの GL01Pでデフォルト設定のまま
暗号化方式は WPA/WPA2
WPA暗号化方式は TKIP+AES
これがちょっと気になるんだけど、PC側はWPA2、TKIPで設定してるけどいいんだよね?
iPhoneはSSIDとパスワード(WPA key)しかいらない。
Windows7は「セキュリティの種類:WPA-パーソナル」「暗号化の種類:TKIP」、「ネットワークセキュリティ」にWPA Keyを設定してつながっている。




2012/11/21

ブリッジとスイッチの本質的な違い


Ethernet, TCP/IPについて勉強し始めた頃、「ブリッジとスイッチ(L2スイッチ、スイッチングハブ)の違いは何か?」という疑問を抱いたことのある人は多いと思う。

よく言われることは、「スイッチはマルチポートである」「スイッチはHW処理である」「スイッチは転送方式が異なる(カットアンドスルー等)」などであるが、私はそれらの違いのどれもブリッジとスイッチの本質的な違いを説明しているようには思えなかった。

しかし、私はようやく本質的な違いを理解した。それはすでに挙げたことであるが「マルチポートであること」である。マルチポートであるというのは単にポート数が増えただけで本質的ではないように思えるが、そうではないのだ。

ブリッジもスイッチもアドレス学習機能を持ち、その原理は同じである。フレームを受信するとその送信元MACアドレスは受信したポートに接続されていると認識し記憶する。その後、記憶してあるMACアドレス宛のフレームを受信したら、そのポートへ送信する。記憶していない未学習のMACアドレス宛のフレームを受信した場合は、受信ポート以外のポートから、そのフレームをコピーして送出する。

このアドレス学習機能の目的は何だろうか?それは「不要なフレーム転送の抑制」である。「あるMACアドレスがどのポートに所属しているかの区別」ではない。確かにこの学習においてアドレスとポートの関連付けはおこなわれるのであるが、それは目的ではなく手段である。

アドレス学習機能の目的が「不要な転送の抑制」であることがわかると、どうしてスイッチがスイッチと呼ばれるようになったかがわかる。スイッチとは初期は単なるマルチポートブリッジでしかなかった。アドレス未学習のときにフレームを受信したポート以外から転送することはポート数が2個だろうとそれより多かろうと同じである。

しかし、ポート数が2個であれば、ブリッジのすることはそのフレームを受信ポートでないひとつのポートから送出するか否かを判断することでしかないが、マルチポートつまり3個以上になると、「受信ポートでない複数のポートのどこから送出するか」を判断することになる。

ブリッジというと、二つの場所を「接続する」というイメージがある。実際に接続することにはなるのだが、そもそもブリッジが登場した目的はノード数の増加とともに増大するコリジョンを削減するためであった。ひとつの大きなコリジョンドメインを分割する目的で考え出された装置なのである。

ブリッジが3つ以上の場所を接続することになっても、それは同じであるが、接続する場所が3つ以上になったことにより、それまでは「出すか出さないか」でしかなかった判断が「どこに出すか」という判断になった。それを判断するための原理は2ポートの時と同じでも機能したのであるが、単なる不要な転送の抑制だけが目的であったのに加え、「どのポートへ転送するか」という目的も兼ねるようになったのである。これは2ポートの場合にはなかったことである。

HW処理になったり、転送方式が改良されたりしたのも、この新しい目的の為である。だからブリッジとスイッチの一番本質的な違いはマルチポートであることである。

2012/11/13

javascriptによる画像ビューア

javascriptがアツい。 javascriptのコンパクトな画像ビューアがあったので、 cgiの中に入れることにした。 ヒアドキュメントを使ったら、文字化けしている。 それは、変数展開によるものであった。

print <<"END_OF_TXT";

apple
banana
$test

END_OF_TXT


とやると、$testが変数展開されてしまう。 それをさせないようにするには、

print <<'END_OF_TXT';


とすればよい。ちなみにそのjavascriptによるビューアは動きが重かったので不採用。




ファイルの拡張子を取り出そうと調べたら、以下のようなソースがあった。

$name = "aaa.jpg";

if( index($name, '.', 0) != -1){
$suffix = (split(/\./, $name))[-1];
}

print $suffix."\n";


なるほどね、ピリオドで区切ってsplitすればいいのか・・・ と思ったがsplitしたものの取り出し方がちょっと変わっている。 私だったら、

@tmp = split /\./, $name;
$suffix = pop(@tmp);


とやるところだ。 おそらくそれを一発でできるのだろうが、どういうことなのかよくわからない。

[-1]で配列の最後を意味するのかな?