質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

1588閲覧

【アイデアがわかない】特定の文字列にリンクを挟む方法における問題点

starrow1103

総合スコア137

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2017/03/30 07:23

編集2017/03/30 07:30

前提とやりたいこと

[前提]
・固有名詞が登録されたリストwords = [a,b,c,d...]がある
・とある文章AA = textが存在する

(実際には固有名詞は映画の作品名、文章はその感想とします。)

[やりたいこと]
・文章Aの中に固有名詞のいずれかが含まれる場合、該当する固有名詞にリンクタグを付与する

やっていること

python

1for word in words: 2 if word in text: 3 replace_word = '<a href="/">%s</a>' % word 4 text = text.replace(word,replace_word)

(↑後で気づいたけど、ifいらないですね)

問題となっていること

仮に、リストwordsの中に同じ文字列を含んでしまうものが存在した時、おかしくなります。

例)映画の作品には、シリーズ化されていてそのタイトルを冠するものが多い

words = ['アイアンマン','アイアンマン2']

この場合、文章を検索した時にまずアイアンマンについてリンクを付与したなら、問題は発生しませんが、
先にアイアンマン2にリンクが付与された場合、その中に含まれるアイアンマンが次に付与されてしまいますよね。

これは、作品名が全く異なっても起こりうる問題であると考えています。

お願いします

この問題を回避する方法を考えています。
良いアイデアがありましたら、ご教授いただけませんでしょうかm(_ _)m

よろしくお願いします。

追記

タイトルの長い順から検索していき、当てはまったタイトルが他のタイトルを含んでいる時、他のタイトルをリストから除外して再ループというのが一番効率的でしょうか、、、

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

もう解決済みですが、wordsの数がそれほど多く無いのであれば、正規表現でもできると思ったので記載いたします。 最長一致の順番でリンクに置き換えていくのは、can110さんと一緒です。

python

1import re 2 3words = ['アイアンマン', 'アイアンマン2', 'アイアンマン3', 'アイアンマン22'] 4 5text = """ 6アイアンマン22アイアンマン3アイアンマン2 7アイアンマン2アイアンマン アイアンマン3 8アイアンマンXアイアンマン22アイアンマン3 9""" 10 11words_str = '|'.join([re.escape(s) for s in sorted(words, key=lambda k: -len(k))]) 12REGEX_KEYWORDS = re.compile(r'({})'.format(words_str), re.MULTILINE) 13result = REGEX_KEYWORDS.sub(r"<a href='/'>\1</a>", text) 14 15print(result)

結果は下記のようになります。

html

1<a href='/'>アイアンマン22</a><a href='/'>アイアンマン3</a><a href='/'>アイアンマン2</a> 2<a href='/'>アイアンマン2</a><a href='/'>アイアンマン</a> <a href='/'>アイアンマン3</a> 3<a href='/'>アイアンマン</a>X<a href='/'>アイアンマン22</a><a href='/'>アイアンマン3</a>

また、はてなキーワードの実装についての考察なども、参考になると思いました。

http://d.hatena.ne.jp/tsugehara/20120909/1347190811

投稿2017/03/30 09:46

tell_k

総合スコア2120

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

starrow1103

2017/03/31 01:10

ありがとうございます! うーむ、今の知識ではちょっと理解に及ばないところがいくつかあるので、ちょっと勉強してみますね。 wordの数が少ないのであれば、という条件付きということから、一度単語帳から「変換リスト」なるものをre.compileで作成しているという感覚でよろしいでしょうか。
tell_k

2017/03/31 07:02 編集

感覚的にはあってますね。より簡単な例だと、正規表現は下記のようなことをやっています。 re.sub(r'(アイアンマン2|アイアンマン)', r'<a>\1</a>', re.MULTILINE) r'(アイアンマン2|アイアンマン)' この正規表現の中の 「|」は or の役割をします。つまりアイアンマン2かアイアンマン にマッチするという意味でです。左から順番にマッチするかチェックされるので、「文字数が長いキーワードを左から順番に並べる」ことをすれば「最長一致」のマッチングができます。 r'<a>\1</a>', その正規表現を ( ) で囲んでグループ化して、マッチしたキーワードを 「\1」があるところに置換しています。 re.MULTILINE re.MULTILINEという引数は複数行のテキストに対しても正規表現を適用するというオプションです。(通常は改行コードが入ってると、それ以降のテキストは正規表現の対象外になります = 1行しか対応してくれない)
guest

0

ベストアンサー

こんな感じですかね。
長い順から探して置換するのは、この手の処理では常套手段です。

Python

1# text中に存在する全wordsを置換する 2def rep_words( words, text): 3 4 # text中のwordを「置換識別子」に置き換える 5 rep_map = {} # 置換識別子 -> 実際に置換したい文字列 のマップ 6 for word in words: 7 if word in text: 8 rep_str = '<<<rep%d>>>' % (len(rep_map) + 1) # 置換識別子 = textに現れないような文字列にする 9 rep_map[rep_str] = '<a href="/">%s</a>' % word 10 text = text.replace( word, rep_str) 11 12 print(text) # テスト出力 13 14 # 置換識別子 -> 置換したい文字列に置き換える 15 for k,v in rep_map.items(): 16 text = text.replace( k,v) 17 18 return text 19 20words = ['アイアンマン','アイアンマン2','アンパンマン'] 21# wordsは長さの降順であること 22words.sort(key=len) 23words.reverse() 24print(words) 25 26print(rep_words(words,'アイアンマン2はアイアンマンとは違う')) 27print(rep_words(words,'アイアンマンはアンパンマンとは違う'))

投稿2017/03/30 07:56

can110

総合スコア38233

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

starrow1103

2017/03/30 08:10

なななるほど!!! 一度、タグ付けをしてタグに応じた値をもう一度割り当てるということですね。 なるほどなるほど・・・。 勉強になりました。ありがとうございましたm(_ _)m
guest

0

Python使ったことないのでアイデアのみですが、
形態素解析でそれなりにいけるかと思います。
完全一致で検索可能かと。
ライブラリ使えば固有名詞は辞書で登録できますし。

ただし学習コストとCPUと結構使います。

投稿2017/03/30 08:02

szk.

総合スコア1400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問