如何从主机下载所有文件

How do I download all the files from a host

我想从主机上获取所有文件并使用 Java 代码将其传输到目录中,例如 https://en.m.wikipedia.org/wiki/2006_ACC_Championship_Game,https://en.m.wikipedia.org/wiki/Bernice,_California,https://en.m.wikipedia.org/wiki/TB10Cs5H3_snoRNA.

然后我想从 https://en.m.wikipedia.org, or specifically https://en.m.wikipedia.org/wiki 下载所有内容,以及它之后的所有文件。

我想我知道使用套接字、URL 和端口执行此操作的方法,但话又说回来...

您可以为此使用 Jsoup。非常容易使用,一个例子是:

Connection.Response response = Jsoup.connect(url).method(Method.GET).execute();

Document doc = response.parse();
String html = doc.html(); //this contains the html in order

然后将包含htmlstring写入您想要的目录中的文件!

维基百科API

您只想下载维基百科文章吗?如果你这样做,那么你可以使用 Wikiepedia's API. I found it on a question here

一个简单的例子copy-pasted from the main page

这 URL 告诉英文维基百科的网络服务 API 向您发送主页的内容:

https://en.wikipedia.org/w/api.php?action=query&titles=Main%20Page&prop=revisions&rvprop=content&format=json

使用任何编程语言为那个 URL 发出 HTTP GET 请求(或者只是在浏览器中访问那个 link),你会得到一个 JSON 文档,其中包括标题为 "Main Page" 的页面的当前 wiki 标记。将格式更改为 jsonfm 将 return 一个 "pretty-printed" HTML 结果有利于调试。

这是 jsonfm URL 作为 easier-to-read 可点击 link。

api.php ? action=query & titles=Main%20Page & prop=revisions & rvprop=content & format=jsonfm

让我们把那个 URL 分开来展示它是如何工作的。

端点

https://en.wikipedia.org/w/api.php

这是端点。它就像 MediaWiki 网络服务的主页 API。 URL 是英文维基百科 API 的基础 URL,正如 https://en.wikipedia.org/wiki/ 是其网站的基础 URL。

如果您正在编写一个使用英语维基百科的程序,您构建的每个 URL 都将从这个基础 URL 开始。如果您使用不同的 MediaWiki 安装,您将需要找到它的端点并使用它。所有维基媒体 wiki 的端点都遵循此模式:

https://en.wikipedia.org/w/api.php      # English Wikipedia API
https://nl.wikipedia.org/w/api.php      # Dutch Wikipedia API
https://commons.wikimedia.org/w/api.php # Wikimedia Commons API

从 r75621 开始,我们对端点进行了 RSD 发现:在任何页面的 HTML 源中查找 link rel="EditURI" 并提取 api.php URL;实际 link 包含附加信息。例如,在这个 wiki 上它是:

<link rel="EditURI" type="application/rsd+xml" href="//www.mediawiki.org/w/api.php?action=rsd" />

否则,没有安全的方法可以在任何 wiki 上定位端点。如果幸运的话,index.php 的完整路径不会隐藏在奇怪的重写规则下,这样您就只需要获取 "edit"(或历史记录)link 并替换index.php(等)与 api.php,或者您将能够使用默认脚本路径(如 w/api.php).

现在让我们继续讨论 URL.

的查询字符串中的参数

格式

format=json

这告诉 API 我们希望数据以 JSON 格式 returned。您可能还想尝试使用 format=jsonfm 来获得适合调试的 HTML 版本的结果。 API 支持其他输出格式,例如 XML 和本机 PHP,但计划删除不太流行的格式 (phab:T95715),因此您可能不想使用它们。

动作

action=query

MediaWiki 网络服务 API 实现了数十个动作,扩展实现了更多;动态生成的 API 帮助记录了 wiki 上的所有可用操作。在这种情况下,我们使用 "query" 操作来获取一些信息。 "query" 操作是 API 最重要的操作之一,它有自己的大量文档。下面只是对一个例子的解释。

Action-specific 参数

titles=Main%20Page

示例 URL 的其余部分包含 "query" 操作使用的参数。在这里,我们告诉 Web 服务 API 我们需要有关名为 "Main Page" 的 Wiki 页面的信息。 (%20 来自 percent-encoding a space。)如果需要查询多个页面,将它们全部放在一个请求中以优化网络和服务器资源:titles=PageA|PageB|PageC。详见查询文档

prop=revisions

您可以请求有关页面的多种信息或属性。该参数告诉 Web 服务 API 我们需要有关页面特定修订版的信息。由于我们没有指定任何修订信息,因此 API 将为我们提供有关最新修订的信息——维基百科的主页,就像现在一样。

rvprop=content

最后,这个参数告诉网络服务API我们想要页面最新版本的内容。如果我们改为传入 rvprop=content|user,我们将获得最新的页面内容和进行最新修订的用户的姓名。

同样,这只是一个例子。此处对查询进行了更详细的解释,API 参考列出了所有可能的操作、rvprop 的所有可能值等。

更通用的方法

这是一种更通用的方法。使用 Jsoup 来抓取 html.

你必须找到一种方法来获取你想要抓取的所有 url。也许将其保存在字符串数组或列表中。然后像这样遍历它:

for (String url : urls) {
    downloadAllFilesOnURL(url);
}

创建一个方法downloadAllFilesOnURL(String url)。这将 url 作为字符串参数。然后使用 JSoup 连接到它。

Document doc = Jsoup.connect(url).timeout(60 * 1000)//60 seconds
                    .userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) "
                    + "AppleWebKit/537.36 (KHTML, like Gecko) "
                    + "Chrome/33.0.1750.152 Safari/537.36").get();

然后,将doc object写入文件

PrintWriter pen = new PrintWriter(<somefilehere>);
pen.println(doc.toString());
pen.close();

获取 url 上的所有 link,以便我们也可以访问它们。这里我们可以递归调用我们之前的方法downloadAllFilesOnURL(String url)。你这样做:

Elements anchorElements = doc.select("a");
for(Element anchor : anchorElements) {
    downloadAllFilesOnURL(anchor.attr("abs:href"));
}

至于图片和其他文件,逻辑是一样的。

Elements imageElements = doc.select("img");
for(Element image : imageElements) {
    downloadFile(image.attr("abs:src");
}

这里我们声明了一个m方法 downloadFile(String url)。此方法从 url 下载文件,如 http://media.example.com/ariticleA/image2.png

Connection.Response response = Jsoup.connect(url).timeout(60 * 1000)
                    .userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) "
                    + "AppleWebKit/537.36 (KHTML, like Gecko) "
                    + "Chrome/33.0.1750.152 Safari/537.36").ignoreContentType(true)
                    .execute();

byte[] bytes = response.bodyAsBytes();

//this is how you write the file
try (FileOutputStream outputStream = new FileOutputStream(<somefilehere>)) {
        outputStream.write(bytes);
} catch (Exception e) {  }

这只是关于如何执行此操作的指南。如果我是被分配来执行此任务的人,这将是我的方法。