Dans un article ici, Nokogiri conclut que lorsque la spécification d'encodage est «nil», il va voir le jeu de caractères du méta élément du html original. J'ai fait. Cette fois, j'ai suivi la documentation officielle pour voir si les conclusions se sont réellement réalisées.
Document officiel de Nokogiri Cette fois, je suivrai ce document officiel. Bien sûr, c'est l'anglais. J'évite généralement les documents officiels en anglais, mais je décide d'aller les voir. Même si vous ne pouvez pas lire l'anglais, vous pouvez lire le code. Peut-être.
Normalement, lors de l'analyse en utilisant Nokogiri, il est écrit comme Nokogiri :: HTML.parse (html)
, mais officiellement il semble être la classe Nokogiri :: HTML :: Document
.
Ouvrez le champ Classe de document, recherchez la méthode .parse
et essayez d'afficher la source avec" afficher la source ".
Source ci-dessous
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
Faisons attention ici en premier
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
est une variable que vous spécifiez généralement html.
En interprétant, si string_or_io
a une méthode ʻencoding, son nom de codage n'est pas ʻASCII-8BIT
, et l'argument ʻencoding n'est pas défini, alors ʻencoding
est string_or_io
. Cela semble être le nom du codage.
Je vois! Donc, si vous n'ouvrez pas html en mode binaire, cela dépend de la façon dont vous ouvrez html (encodage), donc des caractères déformés peuvent se produire après l'analyse!
Alors, que se passe-t-il lorsque vous ouvrez le fichier en mode binaire et que l'argument ʻencoding est
nil`?
Maintenant, concentrons-nous sur ici.
lib/nokogiri/html/document.rb
encoding ||= EncodingReader.detect_encoding(string_or_io)
Si l'argument ʻencoding n'est pas défini, vous pouvez utiliser la méthode ʻEncodingReader.detect_encoding
.
Allez doucement à la méthode ʻEncodingReader.detect_encoding` du document.
Affichez la source comme avant. Source ci-dessous
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
L'argument de méthode chunk
contiendra string_or_io
cette fois, c'est-à-dire ce que vous utilisez normalement comme HTML.
Il existe de nombreuses méthodes inconnues, donc je ne peux pas obtenir la signification exacte, mais y a-t-il une description qui fait référence au jeu de caractères de meta dans le second bloc if? ?? ?? Il semble que la valeur soit retournée par retour, et cette partie semble très suspecte.
Je n'ai pas encore trouvé les détails de la source, mais j'ai l'impression de me rapprocher de la réponse que je recherche. Si je connais les détails de la source, je vais la résumer dans un autre article.
Recommended Posts