【发布时间】:2011-11-28 17:22:59
【问题描述】:
我正在尝试将网页的内容作为字符串获取,我发现这个问题解决了how to write a basic web crawler,它声称(并且似乎)处理编码问题,但是那里提供的代码适用于美国/英语网站,无法正确处理其他语言。
这是一个完整的 Java 类,它演示了我所指的内容:
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class I18NScraper
{
static
{
System.setProperty("http.agent", "");
}
public static final String IE8_USER_AGENT = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; InfoPath.2)";
//https://stackoverflow.com/questions/1381617/simplest-way-to-correctly-load-html-from-web-page-into-a-string-in-java
private static final Pattern CHARSET_PATTERN = Pattern.compile("text/html;\\s+charset=([^\\s]+)\\s*");
public static String getPageContentsFromURL(String page) throws UnsupportedEncodingException, MalformedURLException, IOException {
Reader r = null;
try {
URL url = new URL(page);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setRequestProperty("User-Agent", IE8_USER_AGENT);
Matcher m = CHARSET_PATTERN.matcher(con.getContentType());
/* If Content-Type doesn't match this pre-conception, choose default and
* hope for the best. */
String charset = m.matches() ? m.group(1) : "ISO-8859-1";
r = new InputStreamReader(con.getInputStream(),charset);
StringBuilder buf = new StringBuilder();
while (true) {
int ch = r.read();
if (ch < 0)
break;
buf.append((char) ch);
}
return buf.toString();
} finally {
if(r != null){
r.close();
}
}
}
private static final Pattern TITLE_PATTERN = Pattern.compile("<title>([^<]*)</title>");
public static String getDesc(String page){
Matcher m = TITLE_PATTERN.matcher(page);
if(m.find())
return m.group(1);
return page.contains("<title>")+"";
}
public static void main(String[] args) throws UnsupportedEncodingException, MalformedURLException, IOException{
System.out.println(getDesc(getPageContentsFromURL("http://yandex.ru/yandsearch?text=%D0%A0%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82%D0%BE%D0%B2&lr=223")));
}
}
哪些输出:
??????????? — ??????: ??????? 360 ??? ???????
虽然它应该是:
Результатов — Яндекс: Нашлось 360 млн ответов
你能帮我理解我做错了什么吗?尝试强制 UTF-8 之类的方法无济于事,尽管它是源代码和 HTTP 标头中列出的字符集。
【问题讨论】:
-
你试过Apache Http Client 4.x吗?我发现使用起来更加舒适和稳定。也应该处理大部分的编码问题——尽管下面提到的
<meta>元素 Joel 的处理仍然取决于您,但 EntityUtils 有很长的路要走。 -
你得到'?'的事实而不是 U+FFFD 在这里说明。也许对 ISO-8859-1 有一个隐含的解释。标准库的许多部分默认使用这种编码。
-
你怎么知道解码发生错误,而不是调试输出的编码?在返回字符串之前,您应该打印字符的数值并查看它们作为检查。
-
好吧好吧,看起来这是一个操作系统特定的问题。在我的 Mac 上运行它输出 ????但在我的 Linux 机器上运行就可以了。前几个字符是 10 1056 1077 1079 1091 1083 1100 1090 1072 1090 1086 1074 - 不知道如何解释,但它们实际上不是问号。
标签: java encoding utf-8 internationalization web-crawler