我正在构建一个命令行 php 抓取应用程序,它使用 XPath 来分析 HTML - 问题是每次在循环中加载一个新的 DOMXPath 类实例时,我得到的内存损失大致等于正在加载 XML。脚本运行并运行,慢慢增加内存使用量,直到达到限制并退出。
我试过用 gc_collect_cycles() 强制垃圾回收并且 PHP 仍然没有从旧的 Xpath 请求中取回内存。事实上,DOMXPath 类的定义似乎甚至没有包含析构函数?
所以我的问题是......在我已经提取了必要的数据之后,是否有任何方法可以强制清理 DOMXPath 上的垃圾?可以预见,在类实例上使用 unset 什么都不做。
代码没什么特别的,只是标准的 Xpath 东西:
//Loaded outside of loop
$this->dom = new DOMDocument();
//Inside Loop
$this->dom->loadHTML($output);
$xpath = new DOMXPath($this->dom);
$nodes = $xpath->query("//span[@class='ckass']");
//unset($this->dom) and unset($xpath) doesn't seem to have any effect
正如您在上面看到的,我将新的 DOMDocument 类的实例化保留在循环之外,尽管这似乎并没有提高性能。我什至尝试将 $xpath 类实例从循环中取出并使用 __constructor 方法直接将 DOM 加载到 Xpath 中,内存丢失是相同的。
最佳答案
看到这个答案是她多年没有定论,终于更新了!我现在遇到了类似的问题,结果是 DOMXPath只是泄漏内存,您无法控制它。到目前为止,我还没有搜索过是否已在 bug.php.net 上报告过此问题(这可能有助于稍后进行编辑)。
我发现的问题的“有效”解决方案只是变通方法。基本想法是替换 DOMNodeList Traversable由 DOMXPath::query() 返回包含相同节点的不同节点。
最合适的解决方法是使用 DOMXPathElementsIterator 它允许您在没有内存泄漏的情况下查询问题中的具体 xpath 表达式:
$nodes = new DOMXPathElementsIterator($this->dom, "//span[@class='ckass']");
foreach ($nodes as $span) {
...
}
此类现在是 the development version of Iterator-Garden 的一部分和 $nodes是所有 <span> 的迭代器DOMElements.
此解决方法的缺点是 xpath 结果被限制为 SimpleXMLElement::xpath() 结果(这与 DOMXPath::query() 不同)因为它在内部用于防止内存泄漏。
另一种选择是使用 DOMNodeListIterator 在 DOMNodeList就像 DOMDocument::getElementsByTagname() 返回的那个.然而,这些迭代很慢。
希望这有一些用处,即使这个问题真的很老。它在类似情况下帮助了我。
仅当对象不再被引用(使用)时,调用垃圾收集清理循环才有意义。
例如,如果您创建一个新的 DOMXPath对象相同 DOMDocument一遍又一遍(记住它连接到仍然存在的 DOMDocument),听起来像是你的内存“泄漏”。您只会使用越来越多的内存。
相反,您可以重新使用现有的 DOMXPath重新使用 DOMDocument 对象一直反对。试一试:
//Loaded outside of loop
$this->dom = new DOMDocument();
$xpath = new DOMXPath($this->dom);
//Inside Loop
$this->dom->loadHTML($output);
$nodes = $xpath->query("//span[@class='ckass']");
关于php - DOMDocument/Xpath 在长时间的命令行过程中泄漏内存 - 任何解构此类的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8188729/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll
我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'
有这样的事吗?我想在Ruby程序中使用它。 最佳答案 试试这个http://csl.sublevel3.org/jp2a/此外,Imagemagick可能还有一些东西 关于ruby-是否有将图像文件转换为ASCII艺术的命令行程序或库?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6510445/
在几个项目中,我希望有一个类似rakeserver的rake任务,它将通过任何需要的方式开始为该应用程序提供服务。这是一个示例:task:serverdo%x{bundleexecrackup-p1234}end这行得通,但是当我准备停止它时,按Ctrl+c并没有正常关闭;它中断了Rake任务本身,它说rakeaborted!并给出堆栈跟踪。在某些情况下,我必须执行Ctrl+c两次。我可能可以用Signal.trap写一些东西来更优雅地中断它。有没有更简单的方法? 最佳答案 trap('SIGINT'){puts"Yourmessa
我正在尝试将cucumber项目的用户名和密码置于版本控制之外。有没有办法在命令行上手动将用户名和密码等变量传递给Cucumber脚本?我的备份计划是将它们放在一个YML文件中,然后将该文件添加到gitignore,这样它们就不会被置于版本控制中。 最佳答案 所以,我看到了您对铁皮人的评论,答案是肯定的。cucumberPASSWORD=my_passwordPASSWORD被设置为环境变量,您可以通过将其引用为ENV['PASSWORD']来使用它的值。例如,browser.text_field(:id=>'pwd').setEN
我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几
我的ruby脚本从命令行参数获取某些输入。它检查是否缺少任何命令行参数,然后提示用户输入。但是我无法使用gets从用户那里获得输入。示例代码:test.rbname=""ARGV.eachdo|a|ifa.include?('-n')name=aputs"Argument:#{a}"endendifname==""puts"entername:"name=getsputsnameend运行脚本:rubytest.rbraghav-k错误结果:test.rb:6:in`gets':Nosuchfileordirectory-raghav-k(Errno::ENOENT)fromtes
遍历nokogiri并使用xpath选择元素相当容易。我需要这个反之亦然,意思是:我需要例如在nokogiri节点上调用.to_xpath以获取元素的完整xpath以将其存储在记录中。有人知道这样做的方法吗? 最佳答案 我能想到的最简单的方法是:Nokogiri::CSS.xpath_fornode.css_path编辑:您也可以尝试使用path方法。 关于ruby-如何从nokogiri对象获取标识符(例如xpath)?,我们在StackOverflow上找到一个类似的问题: