抓取非英文网站的编码问题

2023-12-19

我试图将网页的内容作为字符串获取,我发现这个问题解决了如何编写一个基本的网络爬虫 https://stackoverflow.com/questions/1381617/simplest-way-to-correctly-load-html-from-web-page-into-a-string-in-java,它声称(并且似乎)处理编码问题,但是那里提供的适用于美国/英语网站的代码无法正确处理其他语言。

这是一个完整的 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")));
    }
}

哪个输出:

???????????&nbsp;&mdash; ??????: ??????? 360&nbsp;???&nbsp;???????

虽然它应该是:

Результатов&nbsp;&mdash; Яндекс: Нашлось 360&nbsp;млн&nbsp;ответов

你能帮助我理解我做错了什么吗?尝试强制使用 UTF-8 之类的方法并没有帮助,尽管这是源代码和 HTTP 标头中列出的字符集。


确定正确的字符集编码可能很棘手。

您需要结合使用

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) 从字节中检测字符集的启发式方法(参见这个问题 https://stackoverflow.com/questions/499010/java-how-to-determine-the-correct-charset-encoding-of-a-stream)

使用这三个的原因是:

  1. (a) 和 (b) 可能缺失
  2. META Content-Type 可能是错误的(请参阅这个问题 https://stackoverflow.com/questions/7545459/html-file-fetched-using-wget-reported-as-binary-by-less)

如果 (a) 和 (b) 都缺失怎么办?

在这种情况下,您需要使用一些启发式方法来确定正确的编码 - 请参阅这个问题 https://stackoverflow.com/questions/499010/java-how-to-determine-the-correct-charset-encoding-of-a-stream.

我发现这个序列对于可靠地识别 HTML 页面的字符集编码来说是最可靠的:

  1. 使用 HTTP 响应标头 Content-Type(如果存在)
  2. 对响应内容字节使用编码检测器
  3. 使用 HTML META 内容类型

但您可能会选择交换 2 和 3。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

抓取非英文网站的编码问题 的相关文章

随机推荐

  • 隐式参数和函数

    我在考虑 Haskell GHC 中的隐式参数时遇到问题 我有一个函数f 假设隐式参数x 并希望通过应用将其封装在上下文中f to g f x Int gt Int gt Int f n n x g Int gt Int gt Int gt
  • 如何用范围填充可变参数?

    填充可变参数的正确方法是什么 我的尝试看起来像自行车 首先我构建范围然后我将其转换为列表然后到 intarray然后传播它 m getColumns count count 35 toList toIntArray 其中 getColumn
  • 将字符串插入工作表会导致插入数字

    在我的 Google Apps 脚本中 我在电子表格中添加了一行 在附加的这一行中 我尝试插入一个值 0102 的字符串 但是插入时它会转换为数字 102 有没有什么方法可以使用 Google Apps 脚本将值插入到工作表中 而不会格式化
  • Ubuntu 自动从 Github 存储库中拉取

    我在我的服务器上安装了 git 但我希望每当我推送本地所做的更改时它都会从我的 github 存储库中提取 我研究过钩子 但它非常令人困惑 而且我找不到任何教程 有谁知道这是怎么做到的吗 我希望我的服务器在每次提交后从存储库中提取 这看起来
  • JPA 和 PostgreSQL 与 GenerationType.IDENTITY

    我有关于 Postgres 和 GenerationType Identity 与 Sequence 的问题 在这个例子中 Id SequenceGenerator name mytable id seq sequenceName myta
  • PySpark Worker 中 rdd.collect() 上的 ModuleNotFoundError

    我正在 python 中运行 Apache Spark 程序 并且收到一个我无法理解且无法开始调试的错误 我有一个驱动程序 它在名为 hound py 的文件中定义了一个名为 hound 的函数 在同一目录中 我有一个名为 hound ba
  • PHP Websocket 在测试中验证用户身份(传递会话 cookie)

    我正在尝试测试一个场景 一方面 匿名用户应立即断开与 Websocket 连接的连接 另一方面 经过身份验证的用户应保持 Websocket 连接 第一种情况很容易使用下面的代码进行测试 身份验证过程不起作用 对于会话存储 我将 Cooki
  • 具有多种格式的 Moshi LocalDateTime 适配器

    默认情况下 ThreeTenABP LocalDateTime 转换为 date day 10 month 4 year 2018 time hour 3 minute 34 nano 115000000 second 18 我可以编写一个
  • Magento 客户/会话不工作

    这个问题首先被意识到是因为前端的订单历史页面 sales order history 只显示一条短消息 您没有下订单 经过一番调试 发现问题出在这个函数上 Mage getSingleton customer session 它不会返回包含
  • 为什么 Plastic SCM 不断询问我是否信任复制服务器的证书?

    每次运行类似命令时 我开始收到以下提示cm status cs 630 rep MyServer repserver ssl
  • 出现“类型错误...$(...).modal 不是函数

    我正在尝试使用引导模式创建和编辑用户更新注释的函数 在 REACT 项目中 但这是我得到的错误 Uncaught in promise TypeError jquery WEBPACK IMPORTED MODULE 1 default m
  • 查找数组中所有元素都具有特定值的文档

    这基本上是一个简单的问题 但我找不到它的查询函数 示例集合 id 1 foo bar 9 bar 16 id 2 foo bar 9 bar 9 bar 9 示例输出 id 2 foo bar 9 bar 9 bar 9 因为这是唯一一个每
  • python pyplot连接点

    我正在使用一组点制作 pyplot 图 plt plot range 0 10 dictionary key bo 这按照我的预期正确地绘制了点 但是我也希望在这些点之间绘制一条线 我找不到用 pyplot 来做到这一点的方法 我认为这是微
  • Oracle 中完全外连接的奇怪行为 - 如何解释?

    我注意到 Oracle 11 中 FULL OUTER JOIN 的奇怪行为 我正在连接 HR 模式中的表 特别是 EMPLOYEES 和 DEPARTMENTS 例如 以下查询返回 123 行 SELECT FROM employees
  • 使用 $resource 承诺模式缓存数据

    假设我的服务从 resource get 返回一个承诺 我想知道这是否是缓存数据的正确方法 在此示例中 点击后退箭头并返回搜索结果后 我不想再次查询网络服务器 因为我已经有了它们 这是处理这种情况的正确模式吗 下面的示例是查询 Flixte
  • 转换时间字符串格式

    我想将时间数据转换为格式HH mm ss在 JavaScript 中 我的代码有问题 请参阅代码内的注释 function parseTime timeString var timeString timeString toLowerCase
  • 如何简化Java中的印度区字符串? (问题扩展)

    我有一系列印度地区 例如String districts district1 district2 district3 等等 也许是印度的全部或部分地区 认为 District1 district2 district3 是拉贾斯坦邦的区 An
  • 删除 Google 地图圆形/形状

    我正在使用 google maps Circle 方法创建一个 Circle 这一切都工作得很好 但是我怎样才能删除这个圆圈呢 My code var populationOptionsAgain strokeColor c4c4c4 st
  • 如何测试断言?

    我发现如何测试异常或错误 https stackoverflow com a 54241438 6509751 https stackoverflow com a 54241438 6509751 但我如何测试以下内容assert工作正常吗
  • 抓取非英文网站的编码问题

    我试图将网页的内容作为字符串获取 我发现这个问题解决了如何编写一个基本的网络爬虫 https stackoverflow com questions 1381617 simplest way to correctly load html f