我正在尝试将网页的内容作为字符串,我发现这个问题是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标题中列出的字符集。
答案 0 :(得分:2)
确定正确的字符集编码可能很棘手。
您需要使用
的组合a)HTML META Content-Type标签:
<META http-equiv="Content-Type" content="text/html; charset=EUC-JP">
b)HTTP响应头:
Content-Type: text/html; charset=utf-8
c)从字节中检测字符集的启发式方法(参见this question)
使用这三者的原因是:
如果(a)和(b)都缺失怎么办?
在这种情况下,您需要使用一些启发式方法来确定正确的编码 - 请参阅this question。
我发现这个序列是最可靠的,可以有力地识别HTML页面的字符集编码:
但你可以选择交换2和3。
答案 1 :(得分:1)
您遇到的问题是Mac上的编码不支持西里尔文脚本。我不确定它是否适用于Oracle JVM,但是当Apple生产自己的JVM时,the default character encoding for Java was MacRoman.
启动程序时,请指定file.encoding
系统属性以将字符编码设置为UTF-8(默认情况下Mac OS X使用该编码)。请注意,您必须在启动时进行设置:java -Dfile.encoding=UTF-8 ...
;如果你以编程方式设置它(通过调用System.setProperty()
),则为时已晚,设置将被忽略。
每当Java需要将字符编码为字节时 - 例如,当它将文本转换为字节以写入标准输出或错误流时 - 它将使用默认值,除非您明确指定另一个。如果默认编码不能对特定字符进行编码,则替换合适的替换字符。
如果编码可以处理使用的Unicode替换字符,U + FFFD,( )。否则,问号(?)是常用的替换字符。
答案 2 :(得分:0)
Apache Tika包含您想要的实现。很多人都是这样用的。您还可以查看Apache Nutch。另一方面,您根本不必实现自己的爬虫。