Corrigir acentos de uma página copiada com Java

Estou querendo baixar o conteúdo de um site, para analisar. O texto está vindo com acentos. Usei uma função replaceAll, mas não resolveu.

Código

package evangelho.dodia;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

public class EvangelhoDoDia {
	
	private static String removeHTML(String html){
	    String noTagRegex = "<[^>]+>";
	    return html.replaceAll(noTagRegex, "").trim();
	}
	
	private static String corrigirAcentos(String texto){
		String temp = texto;
		// a
		temp.replaceAll("Ã?", "Á").trim();
		temp.replaceAll("ã", "ã").trim();
		temp.replaceAll("á", "á").trim();
		temp.replaceAll("&atilde;", "ã").trim();
		// e
		temp.replaceAll("é", "é").trim();
		temp.replaceAll("ê", "ê").trim();
		temp.replaceAll("&eacute;", "é").trim();
		// i
		temp.replaceAll("í", "í").trim();
		temp.replaceAll("&iacute;", "í").trim();
		// o
		temp.replaceAll("Õ", "Õ").trim();
		temp.replaceAll("ó", "ó").trim();
		temp.replaceAll("õ", "õ").trim();
		temp.replaceAll("&oacute;", "ó").trim();
		// u
		temp.replaceAll("ú", "ú").trim();
		// consoantes
		temp.replaceAll("Ç", "Ç").trim();
		temp.replaceAll("ç", "ç").trim();
		temp.replaceAll("&ccedil;", "ç").trim();
		temp.replaceAll("ñ", "ñ").trim();
		// caracteres especiais
		temp.replaceAll("–", "-").trim();
		temp.replaceAll("	", "").trim();
		temp.replaceAll("“", "\"").trim();
		temp.replaceAll("â€", "\"").trim();
		// limpos para usar
//		texto.replaceAll("", "").trim();
//		texto.replaceAll("", "").trim();
//		texto.replaceAll("", "").trim();
//		texto.replaceAll("", "").trim();
//		texto.replaceAll("", "").trim();
//		texto.replaceAll("", "").trim();
//		texto.replaceAll("", "").trim();
		return temp;
	}
	
	private static String conteudo;

	private static String capturaHTML(String url) {

		try {
			//pega a url informada
			URL u = new URL(url);
			//conecta com o servidor da pagina
			URLConnection uc = u.openConnection();
			//retorna a leitura da pagina
			InputStreamReader isr = new InputStreamReader(uc.getInputStream());
			BufferedReader br = new BufferedReader(isr);

			String inputLine;
			//lê todas as linhas da pagina e armazena tudo na variavel in
			while ((inputLine = br.readLine()) != null) {
				conteudo += (inputLine + "\n");
			}
			
			conteudo = removeHTML(conteudo);
			
			conteudo = corrigirAcentos(conteudo);
			
			System.out.println(conteudo);
			br.close();
			isr.close();
			
			return conteudo;

		} catch (IOException e) {
			e.printStackTrace();
		}

		return url;

	}
	

	public static void main(String[] args) throws Exception {
		
		String pagina = "https://www.cancaonova.com/index.php";
		
		capturaHTML(pagina);
		
	}

}

========================

Minhas dúvidas:

  1. Por que a função de “replaceAll” não funciona?

  2. Tem uma forma mais simples de corrigir os acentos?

Eu testei

	private static String ajeitar(String texto) {
		String s2;
		try {    
			s2 = new String(texto.getBytes("ISO-8859-1"));
//			s2 = new String(texto.getBytes("Windows-1252"));
//			s2 = new String(texto.getBytes("UTF-8"));
			return s2;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "vazio";
		}
	}

Mas também não funcionou. Nenhuma das três codificações.

Agradeço desde já pela ajuda e apoio.

Muito obrigado.

1 curtida
 public static String corrigirAcentos(String texto) {
    String nfdNormalizedString = Normalizer.normalize(texto, Normalizer.Form.NFD);
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    return pattern.matcher(nfdNormalizedString).replaceAll("");
 }

no caso para mudar o valor do texto e receber essa troca você teria que fazer temp=temp.replaceAll("Ã?", "Á").trim();

o que acontece é que o comando replace e o trim só retorna um valor e não modifica o conteúdo. Mas a forma informada acima do “pmlm” é bem melhor para o seu objetivo.

1 curtida

Não funciona por 2 motivos:

  • strings são imutáveis em Java, e métodos que “modificam” a string na verdade retornam outra string com o valor alterado.
    Então na verdade você deveria fazer temp = temp.replaceAll(etc...)
  • o primeiro argumento de replaceAll é uma expressão regular (regex) e no caso Ã? significa "zero ou uma ocorrência de Ã". Ou seja, isso não faz o que você acha que faz:
System.out.println("abc".replaceAll("Ã?", "Á")); // ÁaÁbÁcÁ

No caso, a regex encontra "zero ocorrências de Ã" em todas as posições da string (no início, entre as letras e no final) e substitui essas posições por Á. O resultado é ÁaÁbÁcÁ.

Claro que dá pra arrumar (bastaria usar "Ã\\?"). Mas na verdade não precisa desse monte de replace, pois o que você tem aí é um problema de encoding.


Por padrão, InputStreamReader (e muitas outras classes) usam o charset default que está configurado na JVM (que você pode ver qual é chamando Charset.defaultCharset()). E se o charset default não for o mesmo da página HTML, podem ocorrer esses problemas (a string resultante pode acabar tendo esses caracteres estranhos, como “Ã?”, entre outros).

Sendo assim, você tem que informar que quer usar o mesmo charset da página em questão. Algo assim:

// pega o charset da conexão
static String getCharset(URLConnection uc) {
    if (uc.getContentEncoding() != null) { // pode vir nulo em alguns casos
        return uc.getContentEncoding();
    }
    String contentType = uc.getContentType();
    // o charset pode vir no header Content-Type, exemplo: "text/html; charset=UTF-8"
    if (contentType.contains("; charset=")) {
        return contentType.split("; charset=")[1];
    }
    // se não encontrou nada, retorna o default do sistema
    return Charset.defaultCharset().name();
}

private static String capturaHTML(String url) {
    try {
        URL u = new URL(url);
        URLConnection uc = u.openConnection();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream(), getCharset(uc)))) {
            String inputLine;
            while ((inputLine = br.readLine()) != null) {
                conteudo += (inputLine + "\n");
            }
        }
        conteudo = removeHTML(conteudo);
        System.out.println(conteudo);
        return conteudo;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return url;
}

Também coloquei o BufferedReader em um bloco try-with-resources, que garante que ele é fechado ao final, mesmo se ocorrer alguma exceção.

Assim, lendo com o encoding correto, os acentos já vêm corretamente e você não precisa daquele monte de replace.

E para entender mais sobre encodings, leia aqui e aqui.


Obs: se a ideia era remover os acentos em vez de corrigi-los, aí sim você poderia usar a sugestão do @pmlm. Mas se o arquivo for lido com o encoding errado, o código dele não funcionará, já que o conteúdo não terá os acentos e sim os caracteres estranhos (ou seja, “Ã?” será substituído por “A?”). Então primeiro você corrige o encoding, e depois remove os acentos.

1 curtida

Muito obrigado @hugokotsubo !

1 curtida