LoginSignup
3
0

More than 3 years have passed since last update.

PHPerがPythonの正規表現ライブラリにやられた話

Last updated at Posted at 2019-08-06

はじめに

僕は普段から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だとどうなるかというと、まあこんな感じ。

php
preg_match("/[a-zA-Z0-9]+\.onion/", $row["url"], $matches);
print_r($matches[0]);

じゃあ次。多少Pythonの知識があったので、とりあえず適当に書いてみる。

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() も参照してください)。"

書き直すと以下のようになります。

python
m = re.search(r"[a-zA-Z0-9]+\.onion", row[1])
print(m.group(0))

まとめ

re.matchは文字列の先頭からのみ探し出す。文字列の途中からも探したいならre.searchを使おう。(こいつ^使えばええやん...)

使い分けてる人がいるのかは分からないけど、僕はアップデートでどちらかが無くなることを祈ってます。

てか、リファレンスちゃんと読もうね!!!

3
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0