2 Stimmen

Eine Kleinbuchstaben-ASCII-Zeichenfolge aus einer (möglicherweise codierten) Zeichenfolge zurückgeben, die mit urllib2 oder BeautifulSoup abgerufen wurde.

Ich hole Daten von einer Webseite mit urllib2 ab. Der Inhalt aller Seiten ist in englischer Sprache, daher gibt es kein Problem beim Umgang mit nicht-englischem Text. Die Seiten sind jedoch codiert und enthalten manchmal HTML-Entitäten wie £ oder das Copyright-Symbol usw.

Ich möchte überprüfen, ob Teile einer Seite bestimmte Schlüsselwörter enthalten - jedoch möchte ich dies in einer nicht-unterscheidenden Groß-/Kleinschreibung durchführen (aus offensichtlichen Gründen).

Wie kann ich den zurückgegebenen Seiteninhalt am besten in Kleinbuchstaben konvertieren?

def get_page_content_as_lower_case(url):
    request = urllib2.Request(url)
    page = urllib2.urlopen(request)
    temp = page.read()

    return str(temp).lower() # das funktioniert nicht, weil die Seite UTF-8 Daten enthält

[[Update]]

Ich muss nicht unbedingt urllib2 verwenden, tatsächlich kann ich stattdessen BeautifulSoup verwenden, da ich Daten aus einem bestimmten Element(en) in der Seite abrufen muss - für das BS eine viel bessere Wahl ist. Ich habe den Titel entsprechend geändert.

ALLERDINGS bleibt das Problem bestehen, dass die abgerufenen Daten in einer nicht-ASCII-Codierung (sollte) in UTF-8 vorliegen. Ich habe eine der Seiten überprüft und die Codierung war iso-8859-1.

Da ich mich nur für die englische Sprache interessiere (von englischsprachigen Websites), möchte ich wissen, wie ich eine in Kleinbuchstaben konvertierte ASCII-Zeichenfolge der von der Seite abgerufenen Daten erhalten kann - damit ich einen Groß-/Kleinschreibungstest durchführen kann, ob ein Schlüsselwort im Text gefunden wird.

Ich gehe davon aus, dass die Tatsache, dass ich mich nur auf Englisch (von englischsprachigen Websites) beschränkt habe, die Codierungsvarianten verringert. Ich kenne mich nicht viel mit Codierungen aus, aber ich gehe davon aus, dass die gültigen Optionen sind:

  • ASCII
  • iso-8859-1
  • utf-8

Ist das eine gültige Annahme, und falls ja, gibt es vielleicht eine Möglichkeit, eine 'robuste' Funktion zu schreiben, die eine codierte Zeichenfolge akzeptiert, die englischen Text enthält, und eine in Kleinbuchstaben konvertierte ASCII-Zeichenfolge zurückgibt?

3voto

phihag Punkte 261131

Die Suche nach Zeichenfolgen ohne Beachtung der Groß- und Kleinschreibung ist komplizierter als einfach in der kleingeschriebenen Variante zu suchen. Ein deutscher Benutzer würde beispielsweise erwarten, dass sowohl STRASSE als auch Straße mit dem Suchbegriff Straße übereinstimmen, aber 'STRASSE'.lower() == 'strasse' (und man kann nicht einfach ein doppeltes s mit ß ersetzen - es gibt kein ß in Trasse). Andere Sprachen (insbesondere Türkisch) werden ähnliche Komplikationen haben.

Wenn Sie andere Sprachen als Englisch unterstützen möchten, sollten Sie daher eine Bibliothek verwenden, die eine ordnungsgemäße Groß- und Kleinschreibung behandeln kann (wie Matthew Barnetts regexp).

Dennoch lautet die Methode zum Extrahieren des Inhalts der Seite wie folgt:

import contextlib
def get_page_content(url):
  with contextlib.closing(urllib2.urlopen(url)) as uh:
    content = uh.read().decode('utf-8')
  return content
  # Sie können .lower() auf das Ergebnis anwenden, aber das funktioniert im Allgemeinen nicht

2voto

Acorn Punkte 46345

Oder mit Requests:

page_text = requests.get(url).text
lowercase_text = page_text.lower()

(Requests wird die Antwort automatisch decodieren.)

Wie @tchrist sagt, wird .lower() den Job nicht für Unicode-Text erledigen.

Sie könnten sich diese alternative Regex-Implementierung ansehen, die Case Folding für einen Unicode-case-insensitiven Vergleich implementiert: http://code.google.com/p/mrab-regex-hg/

Es gibt auch Casefolding-Tabellen verfügbar: http://unicode.org/Public/UNIDATA/CaseFolding.txt

1voto

jfs Punkte 370717

BeautifulSoup speichert Daten intern als Unicode, sodass Sie keine manuellen Zeichenkodierungsmanipulationen durchführen müssen.

Um Schlüsselwörter (groß- und kleinschreibungsfrei) in einem Text zu finden (nicht in Attributwerten oder Tag-Namen):

#!/usr/bin/env python
import urllib2
from contextlib import closing 

import regex # pip install regex
from BeautifulSoup import BeautifulSoup

with closing(urllib2.urlopen(URL)) as page:
     soup = BeautifulSoup(page)
     print soup(text=regex.compile(ur'(?fi)\L',
                                   keywords=['Ihre', 'Schlüsselwörter', 'hier', 'eingeben']))

Beispiel (Unicode-Wörter von @tchrist)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import regex
from BeautifulSoup import BeautifulSoup, Comment

html = u'''

  Tag-Namen dürfen nicht übereinstimmen
 Post wird gefunden werden
 dasselbe mit post
 und po
 und po
 dies wird ignoriert

'''

soup = BeautifulSoup(html)

# Kommentare entfernen
comments = soup.findAll(text=lambda t: isinstance(t, Comment))
for comment in comments: comment.extract()

# Text mit Schlüsselwörtern finden (groß- und kleinschreibungsfrei)
print ''.join(soup(text=regex.compile(ur'(?fi)\L', opts=['post', 'li'])))
# Vergleich mit '.lower()'
print '.lower():'
print ''.join(soup(text=lambda t: any(k in t.lower() for k in ['post', 'li'])))
# oder exakte Übereinstimmung
print 'exakte Übereinstimmung:'
print ''.join(soup(text=' dasselbe mit post\n'))

Ausgabe

 Post wird gefunden werden
 dasselbe mit post
 und po
 und po

.lower():
 Post wird gefunden werden
 dasselbe mit post

exakte Übereinstimmung:
 dasselbe mit post

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X