如何从主机下载所有文件
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
然后将包含html
的string
写入您想要的目录中的文件!
维基百科API
您只想下载维基百科文章吗?如果你这样做,那么你可以使用 Wikiepedia's API. I found it on a question here
一个简单的例子copy-pasted from the main page
这 URL 告诉英文维基百科的网络服务 API 向您发送主页的内容:
使用任何编程语言为那个 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 分开来展示它是如何工作的。
端点
这是端点。它就像 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) { }
这只是关于如何执行此操作的指南。如果我是被分配来执行此任务的人,这将是我的方法。
我想从主机上获取所有文件并使用 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
然后将包含html
的string
写入您想要的目录中的文件!
维基百科API
您只想下载维基百科文章吗?如果你这样做,那么你可以使用 Wikiepedia's API. I found it on a question here
一个简单的例子copy-pasted from the main page
这 URL 告诉英文维基百科的网络服务 API 向您发送主页的内容:
使用任何编程语言为那个 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 分开来展示它是如何工作的。
端点
这是端点。它就像 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) { }
这只是关于如何执行此操作的指南。如果我是被分配来执行此任务的人,这将是我的方法。