Ich schreibe einen Crawler in Ruby (1.9), der viel HTML von vielen zufälligen Sites verbraucht.
Beim Versuch, Links zu extrahieren, habe ich mich entschieden, .scan(/href="(.*?)"/i)
anstelle von nokogiri / hpricot (größere Beschleunigung) zu verwenden. Das Problem ist, dass ich jetzt viele " invalid byte sequence in UTF-8
" Fehler erhalte .
Soweit ich verstanden habe, verfügt die net/http
Bibliothek über keine codierungsspezifischen Optionen, und das eingehende Material ist im Grunde nicht richtig gekennzeichnet.
Was wäre der beste Weg, um tatsächlich mit diesen eingehenden Daten zu arbeiten? Ich habe versucht, .encode
die Optionen "Ersetzen" und "Ungültig" festzulegen, aber bisher kein Erfolg ...
109
'U*'
rückgängig zu machen'C*'
?Antworten:
In Ruby 1.9.3 ist es möglich, String.encode zu verwenden, um die ungültigen UTF-8-Sequenzen zu "ignorieren". Hier ist ein Ausschnitt, der sowohl in 1.8 ( iconv ) als auch in 1.9 ( String # encode ) funktioniert :
oder wenn Sie wirklich problematische Eingaben haben, können Sie eine doppelte Konvertierung von UTF-8 nach UTF-16 und zurück nach UTF-8 durchführen:
quelle
file_contents.encode!('UTF-16', 'UTF-8', :invalid => :replace, :replace => '')
file_contents.encode!('UTF-8', 'UTF-16')
force_encoding
. Wenn Sie eine ISO8859-1 als UTF-8 gelesen haben (und diese Zeichenfolge daher ungültige UTF-8 enthält), können Sie sie mit the_string.force_encoding ("ISO8859-1") als ISO8859-1 "neu interpretieren" und einfach arbeiten mit dieser Zeichenfolge in ihrer realen Codierung..encode('UTF-8')
ist , ist das Aufrufen nur ein No-Op, und es werden keine Überprüfungen ausgeführt. Ruby Core-Dokumentation zum Codieren . Wenn Sie es jedoch zuerst in UTF-16 konvertieren, werden alle Überprüfungen auf ungültige Byte-Sequenzen ausgeführt, und die Ersetzungen werden nach Bedarf durchgeführt.Die akzeptierte Antwort oder die andere Antwort funktionieren für mich. Ich habe diesen Beitrag gefunden, der vorgeschlagen hat
Dies hat das Problem für mich behoben.
quelle
Meine aktuelle Lösung lautet:
Dies wird zumindest die Ausnahmen beseitigen, die mein Hauptproblem waren
quelle
valid_encoding?
die zu erkennen scheint, wenn etwas nicht stimmt.val.unpack('C*').pack('U*') if !val.valid_encoding?
.\xB0
Rücken erfolgreich in Gradsymbole. Sogar dasvalid_encoding?
kommt wieder wahr, aber ich überprüfe immer noch, ob es nicht wahr ist und entferne die beleidigenden Charaktere mit Amirs Antwort oben :string.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
. Ich hatte auch dieforce_encoding
Route ausprobiert , aber das schlug fehl.Versuche dies:
quelle
Ich empfehle Ihnen, einen HTML-Parser zu verwenden. Finden Sie einfach den schnellsten.
Das Parsen von HTML ist nicht so einfach, wie es scheint.
Browser analysieren ungültige UTF-8-Sequenzen in UTF-8-HTML-Dokumenten und setzen einfach das Symbol " ". Sobald die ungültige UTF-8-Sequenz im HTML analysiert wurde, ist der resultierende Text eine gültige Zeichenfolge.
Selbst innerhalb von Attributwerten müssen Sie HTML-Entitäten wie amp dekodieren
Hier ist eine großartige Frage, die zusammenfasst, warum Sie HTML nicht zuverlässig mit einem regulären Ausdruck analysieren können: RegEx stimmt mit offenen Tags überein, mit Ausnahme von in sich geschlossenen XHTML-Tags
quelle
Das scheint zu funktionieren:
quelle
quelle
Ich bin auf eine Saite gestoßen, die eine Mischung aus Englisch, Russisch und einigen anderen Alphabeten enthielt, was zu Ausnahmen führte. Ich brauche nur Russisch und Englisch, und das funktioniert derzeit für mich:
quelle
Während Nakilons Lösung funktioniert, zumindest um den Fehler zu überwinden, ließ ich in meinem Fall dieses seltsame F-Ed-Up-Zeichen aus Microsoft Excel in CSV konvertieren, das sich in Ruby als (get this) cyrillic K registrierte Ruby war ein fettgedrucktes K. Um dies zu beheben, habe ich 'iso-8859-1' verwendet, nämlich.
CSV.parse(f, :encoding => "iso-8859-1")
, was meine verrückten deaky kyrillischen K's zu einem viel handlicheren machte/\xCA/
, mit dem ich sie dann entfernen konntestring.gsub!(/\xCA/, '')
quelle
Stellen Sie vor der Verwendung
scan
sicher, dass derContent-Type
Header der angeforderten Seite lautettext/html
, da Links zu Bildern vorhanden sein können, die nicht in UTF-8 codiert sind. Die Seite kann auch nicht HTML sein, wenn Sie einehref
in so etwas wie ein<link>
Element aufgenommen haben. Wie Sie dies überprüfen, hängt davon ab, welche HTTP-Bibliothek Sie verwenden.String#ascii_only?
Stellen Sie dann sicher, dass das Ergebnis nur ASCII mit ist (nicht UTF-8, da HTML nur ASCII verwenden soll, Entitäten können anderweitig verwendet werden). Wenn beide Tests bestanden sind, ist die Verwendung sicherscan
.quelle
Wenn Sie sich nicht für die Daten "interessieren", können Sie einfach Folgendes tun:
search_params = params[:search].valid_encoding? ? params[:search].gsub(/\W+/, '') : "nothing"
Ich habe es nur
valid_encoding?
bestanden. Meins ist ein Suchfeld, und so fand ich immer wieder die gleiche Verrücktheit, also benutzte ich etwas wie: nur um das System nicht kaputt zu machen. Da ich die Benutzererfahrung nicht so kontrolliere, dass sie vor dem Senden dieser Informationen automatisch validiert wird (z. B. automatische Rückmeldung, um "Dummy-up!" Zu sagen), kann ich sie einfach aufnehmen, entfernen und leere Ergebnisse zurückgeben.quelle