SIRIUSからWordPressへ以降するツールで、SIRIUSのファイル生成位置がデフォルトの場合、こんなURLのパターンがある。
- https://ドメイン名/
- https://ドメイン名/カテゴリー名/
- https://ドメイン名/カテゴリー名/記事.html
- https://ドメイン名/カテゴリー名/子カテゴリー名/
- https://ドメイン名/カテゴリー名/子カテゴリー名/記事.html
WordPressへ投稿する際、トップページ(1)以外、つまり記事ページでもカテゴリーでもslugを設定する必要がある。
そこでURLからslugに設定すべき文字列、
2なら「カテゴリー名」
3なら「記事.html」
4なら「子カテゴリー名」
5なら「記事.html」
を取得するコードをreライブラリーを使って、URLからslugにする目的の文字列を取り出すコードを書いてみた。
match = re.search("^https?://.*/(.+)", url)
これでトップページ以外はマッチするので、トップページかどうかは切り分けられる。
そして、match.group(1)に、ドメイン名以降が格納されるハズだから、
catpath = match.group(1).split('/')
と’/’で分割して、最後の部分をslugとすればいいと考えた。
が、これは2重に間違えだった。
まずカテゴリーページのURLの場合、URLの最後が’/’で終わっているので、split()を使って分割すると、分割された最後に空文字のリストが作られてしまう。
つまりslugが空文字になってしまう。
もう一つの間違いは、正規表現”^https?://.*/(.+)”は、ドメイン名までとそれ以降でマッチしているのではなく、
- 記事ページの場合なら、ドメイン+カテゴリー名の後の’/’まで
- 親カテゴリーページの場合なら、ドメイン名の後の’/’まで
- 子カテゴリーページの場合なら、ドメイン+親テゴリー名の後の’/’まで
でマッチしていたのだ。
正規表現の貪欲 (greedy) マッチってやつ。
ということで、group(1)には、始めからslugにすべき文字列の部分だけが格納されている。
でも、これはこれで好都合でもあるので、理解だけ正して正規表現はこのままに。
ただカテゴリーページの場合の最後の’/’は付いたまま。
じゃ、splitは必要なくて、URLの最後に’/’があったら外せばいい、ってことで、
match = re.search("^https?://.*/(.+)/?$", url)
としたのだが、これでもカテゴリーページの場合のslug部分の文字列の最後に’/’は付いたままになってしまう。
URL最後の’/’をマッチオブジェクトのグループの範囲外にしたつもりだったのだが、これも貪欲 (greedy) マッチにハマってしまっていた。
slug部分に当てはめる「(.+)」だと、’.’が最後の’/’も含めて合致すると判断されてしまうので、グループの範囲内になってしまうわけだ。
ということで正解は、
match = re.search("^https?://.*/(.+?)/?$", url)
と、slug部分は貪欲 (greedy) マッチしないようにしてあげること。
これで最後の’/?’の部分が効いてくれるようになって、最後の’/’が外せた。
正規表現、やっぱり奥が深いな。
コメント