Ruby: Ich habe versucht herauszufinden, wohin Nokogiri geht, um die Kodierung selbst zu sehen

Einführung

In einem Artikel hier kommt Nokogiri zu dem Schluss, dass er, wenn die Codierungsspezifikation "Null" ist, den Zeichensatz des Meta-Elements des ursprünglichen HTML-Codes anzeigt. Ich tat. Dieses Mal folgte ich der offiziellen Dokumentation, um zu sehen, ob die Schlussfolgerungen wirklich wahr wurden.

Befolgen Sie die offiziellen Unterlagen

Offizielles Nokogiri-Dokument Dieses Mal werde ich diesem offiziellen Dokument folgen. Natürlich ist es Englisch. Normalerweise vermeide ich offizielle englische Dokumente, aber ich beschließe, sie mir anzusehen. Auch wenn Sie kein Englisch lesen können, können Sie den Code lesen. Vielleicht.

Nokogiri :: HTML :: Document-Klasse

Normalerweise wird es beim Parsen mit Nokogiri als "Nokogiri :: HTML.parse (html)" geschrieben, aber offiziell scheint es die "Nokogiri :: HTML :: Document" -Klasse zu sein. Öffnen Sie das Feld Dokumentklasse, suchen Sie nach der Methode ".parse" und versuchen Sie, die Quelle mit "Quelle anzeigen" anzuzeigen.

Quelle unten

lib/nokogiri/html/document.rb


def parse string_or_io, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML

  options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
  # Give the options to the user
  yield options if block_given?

  if string_or_io.respond_to?(:encoding)
    unless string_or_io.encoding.name == "ASCII-8BIT"
      encoding ||= string_or_io.encoding.name
    end
  end

  if string_or_io.respond_to?(:read)
    url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
    unless encoding
      # Libxml2's parser has poor support for encoding
      # detection.  First, it does not recognize the HTML5
      # style meta charset declaration.  Secondly, even if it
      # successfully detects an encoding hint, it does not
      # re-decode or re-parse the preceding part which may be
      # garbled.
      #
      # EncodingReader aims to perform advanced encoding
      # detection beyond what Libxml2 does, and to emulate
      # rewinding of a stream and make Libxml2 redo parsing
      # from the start when an encoding hint is found.
      string_or_io = EncodingReader.new(string_or_io)
      begin
        return read_io(string_or_io, url, encoding, options.to_i)
      rescue EncodingFound => e
        encoding = e.found_encoding
      end
    end
    return read_io(string_or_io, url, encoding, options.to_i)
  end

  # read_memory pukes on empty docs
  if string_or_io.nil? or string_or_io.empty?
    return encoding ? new.tap { |i| i.encoding = encoding } : new
  end

  encoding ||= EncodingReader.detect_encoding(string_or_io)

  read_memory(string_or_io, url, encoding, options.to_i)
end

Lassen Sie uns hier zuerst darauf achten

lib/nokogiri/html/document.rb


  if string_or_io.respond_to?(:encoding)
    unless string_or_io.encoding.name == "ASCII-8BIT"
      encoding ||= string_or_io.encoding.name
    end
  end

string_or_io ist eine Variable, die Sie normalerweise als HTML angeben. Interpretation: Wenn "string_or_io" eine "Codierungs" -Methode hat, sein Codierungsname nicht "ASCII-8BIT" ist und das "Codierungs" -Argument nicht definiert ist, dann ist "Codierung" "string_or_io" Es scheint der Kodierungsname zu sein.

Das war's! Wenn Sie HTML also nicht im Binärmodus öffnen, hängt es davon ab, wie Sie HTML (Codierung) öffnen, sodass nach dem Parsen verstümmelte Zeichen auftreten können!

Was passiert also, wenn Sie die Datei im Binärmodus öffnen und das Argument "Kodierung" "Null" ist? Konzentrieren wir uns jetzt hier.

lib/nokogiri/html/document.rb


encoding ||= EncodingReader.detect_encoding(string_or_io)

Wenn das Argument "encoding" nicht definiert ist, können Sie die Methode "EncodingReader.detect_encoding" verwenden. Gehen Sie vorsichtig zur Methode "EncodingReader.detect_encoding" des Dokuments.

Zeigen Sie die Quelle wie zuvor an. Quelle unten

lib/nokogiri/html/document.rb


def self.detect_encoding(chunk)
  if Nokogiri.jruby? && EncodingReader.is_jruby_without_fix?
    return EncodingReader.detect_encoding_for_jruby_without_fix(chunk)
  end
  m = chunk.match(/\A(<\?xml[ \t\r\n]+[^>]*>)/) and
    return Nokogiri.XML(m[1]).encoding

  if Nokogiri.jruby?
    m = chunk.match(/(<meta\s)(.*)(charset\s*=\s*([\w-]+))(.*)/i) and
      return m[4]
    catch(:encoding_found) {
      Nokogiri::HTML::SAX::Parser.new(JumpSAXHandler.new(:encoding_found)).parse(chunk)
      nil
    }
  else
    handler = SAXHandler.new
    parser = Nokogiri::HTML::SAX::PushParser.new(handler)
    parser << chunk rescue Nokogiri::SyntaxError
    handler.encoding
  end
end

Das Methodenargument chunk enthält diesmal string_or_io, das heißt, was Sie normalerweise als HTML verwenden.

Es gibt viele unbekannte Methoden, daher kann ich die genaue Bedeutung nicht ermitteln. Gibt es jedoch eine Beschreibung, die sich auf den Zeichensatz von Meta im zweiten if-Block bezieht? ?? ?? Es scheint, dass der Wert von return zurückgegeben wird, und dieser Teil fühlt sich sehr verdächtig an.

schließlich

Ich habe die Details der Quelle noch nicht herausgefunden, aber ich habe das Gefühl, der gesuchten Antwort näher gekommen zu sein. Wenn ich die Details der Quelle kenne, werde ich sie in einem anderen Artikel zusammenfassen.

Recommended Posts

Ruby: Ich habe versucht herauszufinden, wohin Nokogiri geht, um die Kodierung selbst zu sehen
Ich habe versucht herauszufinden, was sich in Java 9 geändert hat
Ich habe die grundlegende Grammatik von Ruby kurz zusammengefasst
Ich habe versucht, die Methode zu erklären
Ich habe versucht, das Problem der "mehrstufigen Auswahl" mit Ruby zu lösen
[Metall] Ich habe versucht, den Fluss bis zum Rendern mit Metall herauszufinden
[Rubiy] Heute Abend habe ich versucht, die Schleifenverarbeitung zusammenzufassen [Zeiten, Pause ...]
Ich habe versucht, die verwendeten Methoden zusammenzufassen
Ich habe versucht, das Iterator-Muster zu implementieren
Ich habe versucht, das Problem der Tribonacci-Sequenz in Ruby mit Wiederholung zu lösen.
Ich habe versucht, die Stream-API zusammenzufassen
Wo kann ich mich nach Februar 2019 über Java-Versionen informieren? Über das Problem
Ich habe versucht, den CPU-Kern mit Ruby voll auszunutzen
[Ruby] Ich habe versucht, die häufigen Methoden in Paiza zusammenzufassen
Ich habe versucht, die Beziehung zwischen Klassen wie java.io.InputStream herauszufinden
[Ruby] Ich habe versucht, die häufigen Methoden mit paiza ② zusammenzufassen
Ich habe versucht, das Problem der Tribonacci-Sequenz in Ruby zu lösen (Zeitlimit 10 Minuten).
So finden Sie die Ursache des Ruby-Fehlers
[Rails] Ich habe versucht, die Version von Rails von 5.0 auf 5.2 zu erhöhen
Ich habe versucht, die Sitzung in Rails zu organisieren
[Ruby-Grundlagen] Ich habe versucht, Module zu lernen (Kapitel 1)
Ich habe versucht, Tomcat so einzustellen, dass das Servlet ausgeführt wird.
Ich möchte den Wert in Ruby erhalten
05. Ich habe versucht, die Quelle von Spring Boot zu löschen
Ich habe versucht, die Kapazität von Spring Boot zu reduzieren
Ich habe versucht, die Methode der gegenseitigen Teilung von Eugrid in Java zu implementieren
Ich möchte herausfinden, welche Java-Version die JAR-Datei hat, die ich habe
Ich musste herausfinden, wo sich der Ordner mit den Eclipse-Plugins auf meinem Mac befand. (Memo)
Ich habe versucht, das Problem mit der Ruby-Karaoke-Maschine zu lösen (es gibt ein Beispiel für die Antwort).
Ich habe versucht, das Problem mit dem Ruby-Bonusgetränk zu lösen (es gibt ein Beispiel für die Antwort).
[SwiftUI] Ich habe versucht herauszufinden, wie es sich für jeden angegebenen Hintergrund ändert
Ich möchte herausfinden, ob die angegebene Zeichenfolge vom Zielzeichencode unterstützt wird
Ich kann das Docker-Image nach dem Update auf Docker Desktop 2.4.0.0 nicht finden
Ich habe versucht, die ähnliche Funktion durch asynchrone Kommunikation zu implementieren
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit spiritueller Technik zu erhöhen
[JDBC] Ich habe versucht, von Java aus auf die SQLite3-Datenbank zuzugreifen.
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
(´-`) .. oO (Ich möchte die Standardausgabe" Hallo "leicht finden.
Ich habe versucht, die Umgebung nach und nach mit Docker aufzubauen
Ich habe versucht, eine Umgebung mit WSL2 + Docker + VSCode zu erstellen
Ich habe versucht, eine Validierung durchzuführen, um zu vereinheitlichen, wie Hash-Tags geschrieben werden
[Ruby] Ich möchte die Reihenfolge der Hash-Tabelle umkehren
Ich habe versucht, das Problem bei der Erstellung von Ruby-Bingokarten zu lösen (es gibt ein Beispiel für die Antwort).