Skip to content

Instantly share code, notes, and snippets.

@creaktive
Created January 16, 2011 14:29
Show Gist options
  • Save creaktive/781832 to your computer and use it in GitHub Desktop.
Save creaktive/781832 to your computer and use it in GitHub Desktop.
encodingless HTML text extractor
#!/usr/bin/perl
use strict;
# Para ter certeza absoluta de que nenhum warning de 'Wide character' escapou
use warnings 'all';
# Somente indica que este arquivo .pl está na codificação UTF-8!!!
use utf8;
# Ignora codificação de entrada
use open IN => ':bytes';
# Usa a codificação de saída padrão do sistema
use open OUT => ':locale';
use Encode;
use HTML::Entities;
use Regexp::Common qw(balanced comment);
# Lê arquivo inteiro de uma vez, ao invés de ler linha por linha
local $/ = undef;
while (my $buf = <>) {
# Se não for UTF-8 válido, assume ISO-8859-1
my $encoding = detect_utf8(\$buf) ? 'utf8' : 'iso-8859-1';
# Processa a codificação
$buf = decode($encoding, $buf);
# Trata tags HTML
$buf =~ s%$RE{comment}{HTML}%%gos;
$buf =~ s%<(script|style)\b[^>]*?>.*?</\1>% %gis;
$buf =~ s%$RE{balanced}{-parens=>'<>'}% %gios;
$buf = decode_entities($buf);
# Extrai somente as palavras, normaliza e imprime
print "\L$1 " while $buf =~ m%([\w\-]+)%g;
}
print "\n";
# detect_utf8(\$string)
# Recebe referência para escalar com string a ser analisada e retorna:
# 0 - $string tem caracteres de 8 bits, não valida como UTF-8;
# 1 - $string tem somente caracteres de 7 bits;
# 2 - $string tem caracteres de 8 bits, valida como UTF-8.
# Algoritmo original em PHP: http://www.php.net/manual/en/function.utf8-encode.php#85293
# Fórmula da conversão: http://home.tiscali.nl/t876506/utf8tbl.html#algo
sub detect_utf8 {
use bytes;
my $str = shift;
my $d = 0;
my $c = 0;
my $b = 0;
my $bits = 0;
my $len = length ${$str};
for (my $i = 0; $i < $len; $i++) {
$c = ord(substr(${$str}, $i, 1));
if ($c >= 128) {
$d++;
if ($c >= 254) {
return 0;
} elsif ($c >= 252) {
$bits = 6;
} elsif ($c >= 248) {
$bits = 5;
} elsif ($c >= 240) {
$bits = 4;
} elsif ($c >= 224) {
$bits = 3;
} elsif ($c >= 192) {
$bits = 2;
} else {
return 0;
}
if (($i + $bits) > $len) {
return 0;
}
while ($bits > 1) {
$i++;
$b = ord(substr(${$str}, $i, 1));
if (($b < 128) || ($b > 191)) {
return 0;
}
$bits--;
}
}
}
return $d ? 2 : 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment