【问题标题】:Extracting specific elements from Wikipedia tables in Java从 Java 中的 Wikipedia 表中提取特定元素
【发布时间】:2016-01-03 21:28:12
【问题描述】:

为了我以后的方便,我决定尝试创建一个 Java 程序,它可以在我的计算机上获取一个目录和一个电视节目的 Wikipedia 条目的 URL,然后继续用该节目重命名该目录中的所有文件名称、“SxEy”和剧集的标题。虽然我相信我有用于重命名文件的工作代码,但我坚持的一件事是填充包含剧集名称的数组。虽然这可以手动完成,但这首先会消除程序的意义,所以我希望能够从互联网上提取信息。

现在有问题的电视节目是Arrow,我现在正在寻找第 2 季的剧集名称。我一直在尝试修改this jsoup 教程以访问这些表,希望在它至少开始工作后缩小到所需的表。我修改后的代码供参考:

package tablescraper;

import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class TableScraper {

public static void main(String[] args) {
    try {
        Document doc = Jsoup.connect("http://en.wikipedia.org/wiki/List_of_Arrow_episodes").get();
        Elements trs = doc.select("table.wikitable tr");

        //remove header row
        trs.remove(0);

        for (Element tr : trs) {

            Elements tds = tr.getElementsByTag("td.summary");
            Element td = tds.first();
            System.out.println("Episode: " + td.toString());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

在目前的状态下,我在System.out.println("Episode: " + td.toString()); 面对java.lang.NullPointerException。我试图在getElementsByTag 语句中添加.summary,希望这只会挑选出具有“摘要”类的元素,这是我需要的元素。

到目前为止,我的方法有误吗?我有什么明显的遗漏吗?你会注意到表格中的每一行都包含一个总结这一集的段落——这种格式的变化是问题的一部分吗?如果我像现在这样迭代每个表行,它会成为一个问题吗?展望未来,我将如何区分页面上的每个表格?如果没有办法针对这个特定来源区分它们,那么这并不是世界末日,如果有必要,我可以简单地列出所有剧集,然后将其缩减为根据需要的剧集编号选择条目范围。

【问题讨论】:

  • 你怎么知道它刚从第 2 季回归?这个doc.select("table.wikitable td.summary") 应该返回所有季节的所有剧集的名称。
  • 我不知道是这样,但这是我的最终目标。现在我想它会浏览页面上包含指定标签的所有表格,但到目前为止还没有运气。通过您的更改,我将如何输出该剧集列表?我会将tr.getElementsByTag 调整为tr.getAllElements 吗?我不熟悉这个库,但是拥有所有剧集的列表肯定会让我离目标更近。

标签: java web-scraping html-table jsoup


【解决方案1】:

页面中必须有类wikitable的表格,其中包含td元素而没有类summary。

因此,最好在输出td 之前插入一个空检查:

Elements tds = tr.getElementsByTag("td.summary");
Element td = tds.first();
if (td != null)
    System.out.println("Episode: " + td.toString());

然后

Elements tds = tr.getElementsByTag("td.summary");

将永远不会返回非空列表,因为没有带有标签 td.summary 的元素。再次使用select 查找匹配选择器td.summary 的后代:

Elements tds = tr.select("td.summary");

最后打印出剧集(即td元素的文本内容)不要使用td.toString()而是td.text()

System.out.println("Episode: " + td.text());

【讨论】:

  • 好的,我已经进行了这个更改,现在错误消失了,但是代码没有返回任何结果。它是否可能只查看该行中的第一项,然后在看到它不属于 summary 类时,移动到下一行?
  • @SimonB tr.getElementsByTag("td.summary") 存在问题。查看我编辑的帖子,
  • 啊我现在明白了。通过此更改,程序现在输出该条目的整个 html,例如输出的第二行是 Episode: "Honor Thy Father" . Excluding the "Episode: " bit, I guess now I can just use substrings to remove everything before >"` 和"< 之后,对吗?第一行不遵循这种格式,但我可以稍后更正。
  • 效果很好,谢谢。 for 循环现在看起来像这样,经过调整以消除语音标记:for (Element tr : trs) { Elements tds = tr.select("td.summary"); Element td = tds.first(); if(td != null){ String episode = td.text(); episode = episode.substring(1, episode.lastIndexOf('"')); System.out.println("Episode: " + episode); } }
猜你喜欢
  • 2018-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
  • 2015-11-18
相关资源
最近更新 更多