はじめに
僕は普段からPHPを使っているネットワークエンジニア(の卵)なのですが、大学の研究室の方針と勉強を兼ねてPythonを使ってみました。
環境
- CentOS 6.10
- PHP 5.3.3
- Python 3.4.10
(大学のサーバ、全然アプデされてない...)
前提
- DBに以下のような約14,000件のデータが入っている。
- 全てのURLへアクセスし、そのサイトが生きているか調べたい。
- 基本的には
xxx.onion
というデータが入っているが、稀にyyy.org zzz.onion
というようなデータが紛れ込んでいる。 - プログラムが出来たら
crontab
で3分に1回実行(全部終わるのに29日かかるとか突っ込まないで!!)
id | url | status |
---|---|---|
1 | uel3b54t4iszmpq6.onion | xxx |
2 | tochka3rmabu4p46.onion | xxx |
3 | qwzxd7r5pbrn7cqv.onion | xxx |
4238 | hiddenwikitor.org hekpblat56lmmnfi.onion | xxx |
じゃあ書いてみよう
まずPHPだとどうなるかというと、まあこんな感じ。
preg_match("/[a-zA-Z0-9]+\.onion/", $row["url"], $matches);
print_r($matches[0]);
じゃあ次。多少Pythonの知識があったので、とりあえず適当に書いてみる。
m = re.match(r"[a-zA-Z0-9]+\.onion", row[1])
print(m.group(0))
動くね、じゃあcrontab
で。
そのときは訪れた
初めは問題なく動いていたのに、先程のデータの4238行目で止まってる。なんでや。
色々調べてみるとリファレンスにも書いてある通り、re.match
は先頭からのみ見ていく。取り出したいURLはTLDがonion
のものなのでyyy.onion zzz.org
のようなデータであれば正常に動作するが、今回入っているデータは逆。つまり、re.search
を使えと。便利なんだが紛らわしい。
re.match(pattern, string, flags=0)
string の先頭で 0 個以上の文字が正規表現 pattern にマッチすれば、対応する マッチオブジェクト を返します。文字列がパターンにマッチしなければ None を返します。これは長さ 0 のマッチとは異なることに注意して下さい。
MULTILINE モードにおいても、re.match() は各行の先頭でマッチするのではなく、文字列の先頭でのみマッチすることに注意してください。
string 中のどこででもマッチさせたいなら、代わりに search() を使ってください (search() vs. match() も参照してください)。"
書き直すと以下のようになります。
m = re.search(r"[a-zA-Z0-9]+\.onion", row[1])
print(m.group(0))
まとめ
re.match
は文字列の先頭からのみ探し出す。文字列の途中からも探したいならre.search
を使おう。(こいつ^
使えばええやん...)
使い分けてる人がいるのかは分からないけど、僕はアップデートでどちらかが無くなることを祈ってます。
てか、リファレンスちゃんと読もうね!!!