7

我编写了一个 PhantomJS 应用程序来爬取我构建的网站并检查要包含的 JavaScript 文件。JavaScript 类似于谷歌,其中一些内联代码加载到另一个 JS 文件中。该应用程序会查找其他 JS 文件,这就是我使用 Phantom 的原因。

预期的结果是什么?

控制台输出应读取大量 URL,然后判断脚本是否已加载。

到底发生了什么?

控制台输出将按预期读取大约 50 个请求,然后开始吐出此错误:

2013-02-21T10:01:23 [FATAL] QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe
QEventDispatcherUNIXPrivate(): Unable to create thread pipe: Too many open files

这是打开页面并搜索脚本的代码块,包括:

page.open(url, function (status) {
    console.log(YELLOW, url, status, CLEAR);
    var found =  page.evaluate(function () {
      if (document.querySelectorAll("script[src='***']").length) {
        return true;
      } else { return false; }
    });

    if (found) {
      console.log(GREEN, 'JavaScript found on', url, CLEAR);
    } else {
      console.log(RED, 'JavaScript not found on', url, CLEAR);
    }
    self.crawledURLs[url] = true;
    self.crawlURLs(self.getAllLinks(page), depth-1);
  });

crawledURLs 对象只是我已经爬过的 url 的一个对象。crawlURLs 函数只是遍历 getAllLinks 函数中的链接,并在所有链接上调用 open 函数,这些链接具有爬虫启动的域的基本域。

编辑

我将代码的最后一块修改如下,但仍然有同样的问题。我已将 page.close() 添加到文件中。

if (!found) {
  console.log(RED, 'JavaScript not found on', url, CLEAR);
}
self.crawledURLs[url] = true;
var links = self.getAllLinks(page);
page.close();
self.crawlURLs(links, depth-1);
4

3 回答 3

6

从文档中:

由于一些技术限制,网页对象可能不会被完全垃圾收集。当反复使用同一个对象时,经常会遇到这种情况。

解决方案是在正确的时间显式调用close()网页对象(即page在许多情况下)。

一些包含的示例,例如follow.js,演示了具有显式关闭的多个页面对象。

于 2013-02-21T16:02:55.110 回答
4

打开文件限制。

即使正确关闭文件,您仍可能遇到此错误。

在搜索了互联网之后,我发现您需要增加单个进程允许打开的文件数量的限制。就我而言,我正在生成包含数百到数千页的 PDF。

根据您正在运行的系统,有不同的方法可以调整此设置,但以下是在Ubuntu服务器上对我有用的方法:

将以下内容添加到末尾/etc/security/limits.conf

# Sets the open file maximum here.
# Generating large PDFs hits the default ceiling (1024) quickly. 
*    hard nofile 65535
*    soft nofile 65535
root hard nofile 65535 # Need these two lines because the wildcards (above)
root soft nofile 65535 # are not applied to the root user as well.

ulimit可以在此处找到该命令的一个很好的参考。

我希望这能让一些人走上正轨。

于 2015-08-06T17:30:48.383 回答
0

在我的 ruby​​ 程序中运行多个线程时出现此错误。我正在使用 Capybara-poltergeist 运行 phantomjs,每个线程都在访问一个页面,打开同一个 CSV 文件并写入它。

我能够通过使用Mutex类来修复它。

lock = Mutex.new
lock.synchronize do
    CSV.open("reservations.csv", "w") do |file|
        file << ["Status","Name","Res-Code","LS-Num","Check-in","Check-out","Talk-URL"]
          $status.length.times do |i|
              file << [$status[i],$guest_name[i],$reservation_code[i],$listing_number[i],$check_in[i],$check_out[i], $talk_url[i]]
          end
        end
        puts "#{user.email} PAGE NUMBER ##{p+1} WRITTEN TO CSV"
    end
end
于 2016-02-20T06:38:20.983 回答