无头浏览器是什么?

70

我希望实现以下功能:登录一个网站,点击一些特定的链接,然后点击下载链接。我想在Windows上作为计划任务或在Linux上作为cron job运行。语言不是很重要,但如果可能的话,我希望能够在屏幕上不显示浏览器窗口的情况下运行。


1
为什么要实例化一个浏览器,如果你不打算显示它呢?大多数编程语言都有用于通过URL传输文件的库。告诉我们你使用的编程语言,我们可以指导你正确的方向。 - Ozgur Ozcitak
3
请告诉我们您是否需要 JavaScript 支持,因为这很重要。一些库没有内置的 JS 解释器。 - Anonymous
14个回答

160

以下是我所知道的一些无头浏览器列表:

  • HtmlUnit - Java。自定义浏览器引擎。有限的JavaScript支持/模拟DOM。开源。
  • Ghost - 仅Python。基于WebKit。完全支持JavaScript。开源。
  • Twill - Python/命令行。自定义浏览器引擎。没有JavaScript。开源。
  • PhantomJS - 命令行/所有平台。基于WebKit。完全支持JavaScript。开源。
  • Awesomium - C++/.NET/所有平台。基于Chromium。完全支持JavaScript。商业/免费。
  • SimpleBrowser - .NET 4/C#。自定义浏览器引擎。没有JavaScript支持。开源。
  • ZombieJS - Node.js。自定义浏览器引擎。支持JavaScript/模拟DOM。开源。基于jsdom
  • EnvJS - 通过Java/Rhino的JavaScript。自定义浏览器引擎。支持JavaScript/模拟DOM。开源。
  • Watir-webdriver with headless gem - 通过WebDriver的Ruby。通过浏览器(Firefox/Chrome/Safari/IE)提供完整的JS支持。
  • Spynner - 仅Python。PyQT和WebKit。
  • jsdom - Node.js。自定义浏览器引擎。通过模拟DOM支持JS。开源。
  • TrifleJS - 使用MSIE(Trident)和V8的PhantomJS端口。开源。
  • ui4j - 纯Java 8解决方案。围绕JavaFx WebKit引擎的包装库,包括无头模式。
  • Chromium Embedded Framework - 全面更新的嵌入式Chromium版本,根据需要进行离屏渲染。C/C++,带有.NET包装器(和其他语言)。由于它是Chromium,因此它支持所有。BSD许可证。
  • Selenium WebDriver - 通过浏览器(Firefox、IE、Chrome、Safari、Opera)提供JavaScript的完全支持。官方支持的bindings为C#、Java、JavaScript、Haskell、Perl、Ruby、PHP、Python、Objective-C和R。非官方绑定可用于QtGo。开源。
无头浏览器通过模拟DOM支持JavaScript,但通常会在一些使用更高级/不常见浏览器功能或具有视觉依赖性的功能(例如通过CSS位置等)的网站上出现问题,因此尽管这些浏览器中的纯JavaScript支持通常是完整的,但实际支持的浏览器功能应被视为部分支持。
(注:此帖子的原始版本仅提到了HtmlUnit,因此有评论。如果您知道其他无头浏览器实现并具有编辑权限,请随意编辑此帖子并添加它们。)

12
HTMLUnit对JS的支持很糟糕。恐怕这并不是解决方案。 - KJW
2
HtmlUnit的javascript一直存在问题,可以将其视为一个无JS的浏览器。 - Michael
2
HtmlUnit和HttpUnit都很遗憾地是Ajax之前的产物。它们是为一个时代编写的,当时Javascript仅用于表单验证(您可以完全忘记像JQuery这样的东西在其中任何一个下工作),从我所读到的内容来看,它们都不太可能支持“现代”Javascript,因为这将要求完全重写它们的Javascript引擎,或者用另一个引擎替换它,其绑定可能与原始引擎非常不同,这将需要对整个框架进行实际上的重写以适应它。 - Bitbang3r
@LuisCantero 谢谢,我已经把它加到列表中了。 - Nathan Ridley
1
我最近使用了在 https://developers.google.com/web/updates/2017/04/headless-chrome 描述的无界面模式下的 Google Chrome。与 Chrome 60 版本一起使用非常容易。 - Samuel Garratt
显示剩余4条评论

5

请看twill,这是一种非常便捷的脚本语言,正好符合您的需求。以下是示例

setlocal username <your username>
setlocal password <your password>

go http://www.slashdot.org/
formvalue 1 unickname $username
formvalue 1 upasswd $password
submit

code 200     # make sure form submission is correct!

如果您需要更多的灵活性,也可以使用Python API


4

请查看基于 JavaScript 的自动化框架 PhantomJS,可在 Windows、Mac OS X、Linux 和其他 *ix 系统上使用。

使用 PhantomJS,您可以做如下操作:

console.log('Loading a web page');

var page = new WebPage();
var url = "http://www.phantomjs.org/";

page.open(url, function (status) {
    // perform your task once the page is ready ...
    phantom.exit();
});

或者评估一个页面的标题:

var page = require('webpage').create();
page.open(url, function (status) {
    var title = page.evaluate(function () {
        return document.title;
    });
    console.log('Page title is ' + title);
});

以下是来自PhantomJS快速入门页面的示例。您甚至可以使用render()方法将页面渲染为PNG、JPEG或PDF格式。


这个答案帮助我在 JavaScript 运行后保存了源代码:https://dev59.com/VGQn5IYBdhLWcg3wamjO#32019723 - Valamas
1
一个相当愚蠢的问题,但也许你测试过了:PhantomJS 是否可用于需要用户名/密码的网站? - Sopalajo de Arrierez

2

我曾经使用Internet Explorer ActiveX控件(WebBrowser, MSHTML)来实现此功能。您可以在不可见的情况下实例化它。

任何支持COM的语言都可以实现,如Delphi、VB6、VB.net、C#、C++等。

当然,这只是一种快速而不太完美的解决方案,可能并不适合您的情况。


2
PhantomJS是一个无界面的基于WebKit的浏览器,可以使用JavaScript进行脚本编写。

1

1

除了自动下载文件(因为那是一个对话框),带有嵌入式 WebControl 的窗体将会做到这一点。

您可以查看 WatinWatin Recorder。它们可能会帮助您使用 C# 代码登录到您的网站,导航到 URL,甚至可能帮助自动化文件下载。

但是,您的情况可能会有所不同。


1
如果链接已知(例如,您不必在页面上搜索它们),那么您可能可以使用 wget。我相信它会在多次获取之间执行状态管理。
如果你更加有进取心,那么我会深入研究Python 3.0中的新功能。他们重新设计了HTTP堆栈的接口,并且在我看来,拥有一个非常好的接口,可以用于这种类型的脚本编写。

1

0

你不能只用一个下载管理器吗?

有更好的选择,但FlashGet具有浏览器集成功能,并支持身份验证。你可以登录,点击一堆链接并将它们排队并安排下载。

你可以编写一个作为代理的程序,捕获特定链接并将它们排队以供稍后下载,或者编写一个JavaScript书签工具,修改链接以转到"http://localhost:1234/download_queuer?url=" + $link.href,然后将其排队下载 - 但这样做就相当于重新发明了下载管理器的轮子,而且在进行身份验证时可能会更加复杂。

或者,如果你希望“登录,点击链接”部分也自动化 - 可以研究一下屏幕抓取..基本上,你通过一个HTTP库加载页面,找到下载链接并下载它们。

以下是使用Python的简化示例:

import urllib
from BeautifulSoup import BeautifulSoup
src = urllib.urlopen("http://%s:%s@example.com" % ("username", "password"))
soup = BeautifulSoup(src)

for link_tag in soup.findAll("a"):
    link = link_tag["href"]
    filename = link.split("/")[-1] # get everything after last /
    urllib.urlretrieve(link, filename)

这将使用“用户名”和“密码”进行身份验证,下载example.com上的每个链接。当然,您可以使用BeautifulSoup的HTML选择器查找更具体的链接(例如,您可以查找所有带有“download”类的链接或以http://cdn.example.com开头的URL)。

您几乎可以在任何语言中执行相同的操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接