2016-05-10 8 views
1

Ich möchte zu jedem Wort in einem Text einen Link hinzufügen.Fügen Sie einen Link zu jedem Wort hinzu, um Interpunktion, Wendungen und Unicode zu berücksichtigen.

Beispieltext:
"He's <i>certain</i> in America's “West,” it could’ve been possible for gunfights to erupt at any time anywhere," he said holding a gun in his hand.

Wunschergebnis:.

"<a href='xxx.com?word=he'>He</a>'s 
<i><a href='xxx.com?word=certain'>certain</a></i> 
<a href='xxx.com?word=in'>in</a> 
<a href='xxx.com?word=america'>America</a>'s 
“<a href='xxx.com?word=west'>West</a>,” 
<a href='xxx.com?word=it'>it</a> 
<a href='xxx.com?word=could'>could</a>'ve 
.... etc 

(ich die Ausgabe in mehrere aufgeteilt, um es einfacher zu machen, hier zu lesen Die tatsächliche Ausgabe alle eine Zeichenfolge sein soll, zB :

"<a href='xxx.com?word=he'>He</a>'s <i><a href='xxx.com?word=certain'>certain</a></i> <a href='xxx.com?word=in'>in</a> <a href='xxx.com?word=america'>America</a>'s “<a href='xxx.com?word=west'>West</a>,” <a href='xxx.com?word=it'>it</a> <a href='xxx.com?word=could'>could</a>'ve ... etc 

Jedes Wort sollte eine Verbindung haben, die das Wort ist, das von der Interpunktion und von co ausgenommen wird Hinweise. Links sind Kleinbuchstaben. Interpunktion und Kontraktionen sollten keine Links erhalten. Wörter und Interpunktion sind utf-8 mit vielen Unicode-Zeichen. Das einzige HTML-Element, auf das es stoßen wird, ist <i> und </i>, also ist es nicht HTML-Parsing, nur dieses eine Tag-Paar. Die Verbindung sollte auf dem Wort innerhalb der <i> < -></i> Tags sein.

Mein Code unten für einfache Testfälle gearbeitet, aber es Probleme für echte Texte hat, die länger sind und sich wiederholende Wörter und <i> tags:

# -*- coding: utf-8 -*- 
import re 

def addLinks(s): 
    #adds a link to dictionary for every word in text 
    link = "xxx.com?word=" 

    #strip out 's, 'd, 'l, 'm, 've, 're 
    #then split on punctuation 
    words = filter(None, re.split("[, \-!?:_;\"“”‘’‹›«»]+", re.sub("'[(s|d|l|m|(ve)|(re)]? ", " ", s))) 
    for w in words: 
     linkedWord = "<a href=#'" + link + w.lower() + "'>" + w + "</a>" 
     s = s.replace(w,linkedWord,1) 
    return s 

s = """ 
"I'm <i>certain</i> in America's “West,” it could’ve been possible for gunfights to erupt at any time anywhere," he said holding a gun in his hand. 
""" 
print addLinks(s) 

Meine Probleme:

  • Wie umgehen mit Wörtern, die in einem Satz wiederholt werden, entweder exakte Wiederholungen ("in" < -> "in") oder mit Interpunktion und/oder Großschreibung ("He's" < -> "he") oder Teilwörter ("gun" < - > "Schießerei", "any" < -> "überall"). Es wäre einfacher, wenn es genau auf Leerzeichen aufgeteilt wäre, aber durch das Entfernen von Kontraktionen und das anschließende Aufspalten von Satzzeichen kann ich nicht herausfinden, wie man die verknüpften Wörter sauber in die Zeichenkette einfügt.
  • Meine Regex, um Kontraktionen loszuwerden, funktioniert für einzelne Buchstaben wie 'm und' d, funktioniert aber nicht für 've und' re.
  • ich kann nicht herausfinden, wie man mit <i> Tags beschäftigen, zum Beispiel <i>certain</i> in <i><a href="xxx.com?word=certain">certain</a></i>

machen Ich tue dies in Python 2.7, aber this answer für Javascript ist ähnlich und arbeitet mit Unicode, aber berücksichtigt meine Probleme wie Interpunktion nicht.

+0

Wie funktioniert der Code nicht mit Kapitalisierung und wiederholte Worte umgehen? (Ie, was bekommen Sie jetzt?) Auf einen Blick sollte eine einfache Substitution wie diese 're (r "(?! I>) (\ w +)", r "\1", s) 'nur funktionieren nett. – usr2564301

+0

Natürliche Sprache hat viele Dämonen, erfinde das Rad nicht neu. Sehen Sie in [Pythons Natural Language Toolkit] (http://www.nltk.org/) nach. –

+0

@RadLexus: Meine Wiederholung Problem ist, weil ich eine Schleife verwendet, um jedes gefundene Wort zu ersetzen, so dass es "Waffe" in "Schießerei" gefunden, was ist nicht was ich will. Danke für deine kluge Idee: es funktioniert ziemlich gut, aber es macht Links zu Kontraktionen wie 've,' d; Wie im Beispiel versuche ich, keine Links auf ihnen zu haben. Außerdem muss der href-Link nur aus Kleinbuchstaben bestehen, während der Text genau so bleibt, wie er überall ist. –

Antwort

1

Reguläre Ausdrücke können Ihnen helfen.

Um Wörter, beliebiger Länge, können Sie \w+ verwenden. Um die einzelnen Tags <i> und </i> zu ignorieren, können Sie ein Lookahead hinzufügen: (?!>). Dies entspricht sowohl den offenen als auch den geschlossenen Tags. Um schließlich die rechte Seite der Kontraktionen zu ignorieren, können Sie vor dem eigentlichen Spiel einen Lookbehind hinzufügen: (?<!').

Um eine Kleinbuchstabenversion des gefundenen Musters einzufügen, verwenden Sie eine Callback-Funktion (von Using a regular expression to replace upper case repeated letters in python with a single lowercase letter). Die Rückruf-Lambda-Funktion fügt die Kleinbuchstabeversion der gefundenen Übereinstimmung ein, die von den Codes <a= umgeben ist, und erstellt die gesamte Ersetzungszeichenfolge auf einmal.

Das führt uns zu

import re 

s = """ 
"I'm <i>certain</i> in America's “West,” it could’ve been possible for gunfights 
to erupt at any time anywhere," he said holding a gun in his hand. 
""" 

callback = lambda pat: '<a href="xxx.com?word='+pat.group(1).lower()+'">'+pat.group(1)+'</a>' 
result = re.sub(r"(?<!')(?!i>)(\w+)", callback, s) 

wo result als

am Ende wird
"<a href="xxx.com?word=i">I</a>'m <i><a href="xxx.com?word=certain"> 
certain</a></i> <a href="xxx.com?word=in">in</a> <a href="xxx.com? 
word=america">America</a>'s "<a href="xxx.com?word=west">West</a>," ... 
+0

Wow, sehr nett! Danke für den cleveren Code, Regex Genie :). Und danke für die Erklärung, ich habe viel gelernt. –

Verwandte Themen