【问题标题】:Capture a download link redirected by a page (WGET)捕获由页面重定向的下载链接 (WGET)
【发布时间】:2019-04-10 21:27:08
【问题描述】:

这是我的问题。

我目前正在为我编写一个脚本,它可以自动下载一些我用来“清理”我的计算机的软件。

我已经能够使用像这样的下载 URL 进行下载:“https://www.driverscloud.com/plugins/DriversCloud_Win.exe”,但不能使用像这样的“https://www.ccleaner.com/fr-fr/ccleaner/download/standard”这样的短时间等待后重定向到下载 URL 的 URL。

我可以看到问题是我没有给 Wget 直接下载地址,但我希望能够使用地址“https://www.ccleaner.com/fr-fr/ccleaner/download/standard”来完成,因为 Piriform(Ccleaner 的开发者)更新了软件非常有规律,下载地址根据版本号变化(例如:https://download.ccleaner.com/ccsetup547.exe -> https://download.ccleaner.com/ccsetup548.exe)。

那么我怎么能要求 Wget 获取页面中包含的下载链接而不是下载页面本身(因为我在 URL“https://www.ccleaner.com/fr-fr/ccleaner/download/standard”的末尾得到一个名为“标准”的文件?

如果您有使用 Wget 或其他工具(如 Curl)的解决方案,我会很高兴 :)。

提前谢谢你。

【问题讨论】:

    标签: windows url redirect download wget


    【解决方案1】:

    您不需要 PHP。 wget 本身就足以完成这项简单的工作:)

    这是您需要的命令(我将在下面给出细分):

    $ wget -r -l 1 --span-hosts --accept-regex='.*download.ccleaner.com/.*.exe' -erobots=off -nH https://www.ccleaner.com/fr-fr/ccleaner/download/standard
    

    现在,详细了解它的作用:

    • -r: 启用递归,因为我们想要跟随提供页面上的链接
    • -l 1:我们只想递归一层,因为所需的 URL 在同一页面上
    • --span-hosts:所需文件与我们提供的原始 URL 位于不同的主机上。所以我们要求 wget 在使用递归时跨主机
    • --accept-regex=...:这指定了将通过递归访问的链接的正则表达式。由于我们只需要一个文件并且知道模式,因此我们制作了非常具体的正则表达式。
    • -erobots=offdownload.ccleaner.com 主机有一个 robots.txt,它禁止所有用户代理。但我们不会抓取域,因此请禁用遵守 robots 文件
    • -nH:不要创建特定于主机的目录。这意味着 exe 现在将直接下载到您当前的文件夹中。

    如果您想要更多的自动化,您还可以在上述命令中附加&& rm -r fr-fr/ 以删除您下载的基本页面,以便获得正确的链接。

    享受吧!

    编辑:由于 OP 在 Windows 上,这里有一个专门用于在 Windows 上运行的更新命令。它不会单引号正则表达式字符串,因为这会导致 Windows shell 将正则表达式作为带单引号的字符串传递。

    $ wget -r -l 1 --span-hosts --accept-regex=.*download.ccleaner.com/.*.exe -erobots=off -nH https://www.ccleaner.com/fr-fr/ccleaner/download/standard
    

    【讨论】:

    • 谢谢你的回答,但我试过了,它仍然下载了一个名为“标准”的文件,没有扩展名。看起来我无法按照这个网站上的重定向。
    • 这不应该发生。您可以在该命令中添加-d,然后共享整个输出吗?把它放在pastebin上?我可以完美地运行这个命令,所以我想调查一下为什么它对你的不起作用
    • 抱歉来晚了,这里是加了-d的命令的pastebinpastebin.com/Ux7rrc49
    • 我明白了。看来您的正则表达式后端是问题所在。出于好奇,您能否也发布wget --version 的结果?解决您的问题的一种方法是使用 '.*download.ccleaner.com\/.*.exe' 作为正则表达式字符串。 (注意斜线已被转义)
    • 我尝试了斜线转义的解决方案,同样的问题。我有一个文件夹和子文件夹 -> fr-fr/ccleaner/download 里面有一个名为 standard 的文件。
    【解决方案2】:

    wget蜘蛛模式可能可以做到,但这不是curl和wget的工作,你需要获取下载页面,然后将下载url提取到最新从那个 html 的版本,一些页面还在下载页面中提供了一个 cookie,并且要求您提交这个 cookie 来下载实际的文件,这是一个可以理解 HTTP 和 HTML 的语言的工作。 PHP就是这样一种语言,以ccleaner的下载页面为例:

    #!/usr/bin/env php
    <?php
    $ch = curl_init("https://www.ccleaner.com/fr-fr/ccleaner/download/standard");
    curl_setopt_array($ch, array(
        CURLOPT_COOKIEFILE => '',
        CURLOPT_ENCODING => '',
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_SSL_VERIFYPEER => 0
    ));
    $html = curl_exec($ch);
    $domd = @DOMDocument::loadHTML($html);
    $xp = new DOMXPath($domd);
    $download_element = $xp->query('//a[contains(text(),"start the download")]')->item(0);
    $download_url = $download_element->getAttribute("href");
    $download_name = basename($download_url); // fetching it from the headers of the download would be more reliable but cba
    echo "download name: \"{$download_name}\" - url: {$download_url}\n";
    curl_setopt($ch, CURLOPT_URL, $download_url);
    $installer_binary = curl_exec($ch);
    file_put_contents($download_name, $installer_binary);
    

    此脚本获取下载页面,然后提取包含文本 start the download&lt;a href="download_url"&gt;start the download&lt;/a&gt; 元素的“href”(url)属性,然后下载该 url 指向的任何内容。这超出了 wget/curl 的范围,请使用脚本语言。

    【讨论】:

    • 感谢您的出色工作,我没想到 PHP 解决方案。我的新问题是:我可以从我的批处理脚本启动 PHP 脚本吗? (因为我忘了说我在 Windows 上)。
    • @Spekuloos 当然,如果 php 在计算机上可用。 windows PHP 构建在这里可用windows.php.net/download - 你可以从像C:\php\php.exe script.php 这样的批处理脚本调用,或者如果php.exe 的文件夹被添加到windows 的%path% 变量中,你可以像php script.php 一样运行它(我通常添加php到我自己系统上的路径变量)
    • 好的,就我而言,我只是将 php 文件夹放在我的项目文件夹中,并在我的批处理脚本中使用相对路径。还有一个问题。当我启动脚本时,它说 curl_init 不是一个定义的函数。我必须下载图书馆或其他东西吗?编辑:我的 php 文件夹中没有任何 php.ini 正常吗?
    • @Spekuloos 没有。 php.exe 旁边是一个名为php.ini-development 的文件,将其重命名为php.ini,然后在记事本中打开php.ini,你会发现有一行写着;extension=curl,去掉那一行的分号(这样就变成了@ 987654334@),然后保存。那么 curl_init 应该可以工作
    • @Spekuloos 我刚刚想到:因为您要使用受 httpS SSL/TLS 保护的网站,您可能还需要对 ;extension=openssl 行做同样的事情(libcurl 可能使用openssl 解密 httpS)
    猜你喜欢
    • 1970-01-01
    • 2013-04-03
    • 2011-09-11
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多