Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何正确地爬行?_Ruby_Xpath_Web Crawler_Nokogiri_Rexml - Fatal编程技术网

Ruby 如何正确地爬行?

Ruby 如何正确地爬行?,ruby,xpath,web-crawler,nokogiri,rexml,Ruby,Xpath,Web Crawler,Nokogiri,Rexml,一个月来,我一直在与Nokogiri、REXML和Ruby一起工作和修补。我有一个巨大的数据库,我正试图爬。我正在抓取的是HTML链接和XML文件 我要抓取并存储在CSV文件中的确切的43612个XML文件 我的脚本可以在抓取500个xml文件的情况下运行,但如果抓取的文件较大,则会占用太多时间,并且会冻结或出现其他问题 我在这里将代码分为几部分,以便阅读,整个脚本/代码如下: 我使用了两个库,因为我在nokogiri找不到一个方法来完成这一切。我个人觉得REXML更容易使用 我的问题是:怎样才

一个月来,我一直在与Nokogiri、REXML和Ruby一起工作和修补。我有一个巨大的数据库,我正试图爬。我正在抓取的是HTML链接和XML文件

我要抓取并存储在CSV文件中的确切的43612个XML文件

我的脚本可以在抓取500个xml文件的情况下运行,但如果抓取的文件较大,则会占用太多时间,并且会冻结或出现其他问题

我在这里将代码分为几部分,以便阅读,整个脚本/代码如下:

我使用了两个库,因为我在nokogiri找不到一个方法来完成这一切。我个人觉得REXML更容易使用

我的问题是:怎样才能把它修好,让我一个星期都爬不动?如何让它跑得更快

这是我的剧本:

需要必要的库:

require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'rexml/document'
require 'csv'
include REXML
@urls = Array.new 
@ID = Array.new
@titleSv = Array.new
@titleEn = Array.new
@identifier = Array.new
@typeOfLevel = Array.new
创建一组数组来存储抓取的数据:

require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'rexml/document'
require 'csv'
include REXML
@urls = Array.new 
@ID = Array.new
@titleSv = Array.new
@titleEn = Array.new
@identifier = Array.new
@typeOfLevel = Array.new
从规范站点获取所有xml链接,并将它们存储在名为@URL的数组中

htmldoc = Nokogiri::HTML(open('http://testnavet.skolverket.se/SusaNavExport/EmilExporter?GetEvent&EMILVersion=1.1&NotExpired&EEFormOfStudy=normal&EIAcademicType=UoH&SelectEI'))

htmldoc.xpath('//a/@href').each do |links|
  @urls << links.content
end
htmldoc=Nokogiri::HTML(打开http://testnavet.skolverket.se/SusaNavExport/EmilExporter?GetEvent&EMILVersion=1.1&NotExpired&EEFormOfStudy=normal&EIAcademicType=UoH&SelectEI'))
htmldoc.xpath('//a/@href')。每个都有链接|

@URL由于代码的结构方式,很难确定确切的问题。下面是一些提高速度和构建程序的建议,以便更容易找到阻碍您的因素

图书馆 您在这里使用了很多可能不必要的库

您可以同时使用
REXML
Nokogiri
。他们都做同样的工作。除了
Nokogiri
在这方面做得更好()

使用散列 使用一组散列,而不是将数据存储在15个数组中的
索引中

比如说,

items = Set.new

doc.xpath('//a/@href').each do |url|
  item = {}
  item[:url] = url.content
  items << item
end

items.each do |item|
  xml = Nokogiri::XML(open(item[:url]))

  item[:id] = xml.root['id']
  ...
end
移动方法的公用项

def get_value(xml, path)
   str = ''
   xml.elements.each(path) do |e|
     str = e.text.to_s
     next if str.empty?
   end

   str
end
并将任何常量移到另一个散列中

xml_paths = {
  :title_sv => "/educationInfo/titles/title[1] | /ns:educationInfo/ns:titles/ns:title[1]",
  :title_en => "/educationInfo/titles/title[2] | /ns:educationInfo/ns:titles/ns:title[2]",
  ...
}
现在,您可以将这些技术结合起来,生成更干净的代码

item[:title_sv] = get_value(xml, xml_paths[:title_sv])
item[:title_en] = get_value(xml, xml_paths[:title_en])

我希望这有帮助

由于代码的结构方式,很难精确定位问题。下面是一些提高速度和构建程序的建议,以便更容易找到阻碍您的因素

图书馆 您在这里使用了很多可能不必要的库

您可以同时使用
REXML
Nokogiri
。他们都做同样的工作。除了
Nokogiri
在这方面做得更好()

使用散列 使用一组散列,而不是将数据存储在15个数组中的
索引中

比如说,

items = Set.new

doc.xpath('//a/@href').each do |url|
  item = {}
  item[:url] = url.content
  items << item
end

items.each do |item|
  xml = Nokogiri::XML(open(item[:url]))

  item[:id] = xml.root['id']
  ...
end
移动方法的公用项

def get_value(xml, path)
   str = ''
   xml.elements.each(path) do |e|
     str = e.text.to_s
     next if str.empty?
   end

   str
end
并将任何常量移到另一个散列中

xml_paths = {
  :title_sv => "/educationInfo/titles/title[1] | /ns:educationInfo/ns:titles/ns:title[1]",
  :title_en => "/educationInfo/titles/title[2] | /ns:educationInfo/ns:titles/ns:title[2]",
  ...
}
现在,您可以将这些技术结合起来,生成更干净的代码

item[:title_sv] = get_value(xml, xml_paths[:title_sv])
item[:title_en] = get_value(xml, xml_paths[:title_en])

我希望这有帮助

没有你的固定装置它就不能工作。我相信你应该像@Ian Bishop说的那样重构你的解析代码

require 'rubygems'
require 'pioneer'
require 'nokogiri'
require 'rexml/document'
require 'csv'

class Links < Pioneer::Base
  include REXML
  def locations
    ["http://testnavet.skolverket.se/SusaNavExport/EmilExporter?GetEvent&EMILVersion=1.1&NotExpired&EEFormOfStudy=normal&EIAcademicType=UoH&SelectEI"]
  end

  def processing(req)
    doc = Nokogiri::HTML(req.response.response)
    htmldoc.xpath('//a/@href').map do |links|
      links.content
    end
  end
end

class Crawler < Pioneer::Base
  include REXML
  def locations
    Links.new.start.flatten
  end

  def processing(req)
    xmldoc = REXML::Document.new(req.respone.response)
    root = xmldoc.root
    id = root.attributes["id"]
    xmldoc.elements.each("/educationInfo/titles/title[1] | /ns:educationInfo/ns:titles/ns:title[1]") do |e|
      title = e.text.to_s
      CSV.open("eduction_normal.csv", "a") do |f|
        f << [id, title ...]
      end
    end
  end
end

Crawler.start
# or you can run 100 concurrent processes
Crawler.start(concurrency: 100)
需要“rubygems”
需要“先锋”
需要“nokogiri”
需要“rexml/文档”
需要“csv”
类链接如果没有你的固定装置,它就不能工作。我相信你应该像@Ian Bishop说的那样重构你的解析代码

require 'rubygems'
require 'pioneer'
require 'nokogiri'
require 'rexml/document'
require 'csv'

class Links < Pioneer::Base
  include REXML
  def locations
    ["http://testnavet.skolverket.se/SusaNavExport/EmilExporter?GetEvent&EMILVersion=1.1&NotExpired&EEFormOfStudy=normal&EIAcademicType=UoH&SelectEI"]
  end

  def processing(req)
    doc = Nokogiri::HTML(req.response.response)
    htmldoc.xpath('//a/@href').map do |links|
      links.content
    end
  end
end

class Crawler < Pioneer::Base
  include REXML
  def locations
    Links.new.start.flatten
  end

  def processing(req)
    xmldoc = REXML::Document.new(req.respone.response)
    root = xmldoc.root
    id = root.attributes["id"]
    xmldoc.elements.each("/educationInfo/titles/title[1] | /ns:educationInfo/ns:titles/ns:title[1]") do |e|
      title = e.text.to_s
      CSV.open("eduction_normal.csv", "a") do |f|
        f << [id, title ...]
      end
    end
  end
end

Crawler.start
# or you can run 100 concurrent processes
Crawler.start(concurrency: 100)
需要“rubygems”
需要“先锋”
需要“nokogiri”
需要“rexml/文档”
需要“csv”
类链接f如果你真的想加速它,你必须同时进行

最简单的方法之一是安装JRuby,然后运行应用程序,只需稍加修改:安装“peach”或“pmap”gems,然后将
项更改为
项。peach(n)
(并行),其中
n
是线程数。每个CPU核心至少需要一个线程,但如果将I/O放入循环中,则需要更多线程


另外,使用Nokogiri,速度要快得多。如果您需要解决与Nokogiri有关的特定问题,请单独提出Nokogiri问题。我相信它可以满足您的需要。

如果您真的想加快速度,您必须同时运行

最简单的方法之一是安装JRuby,然后运行应用程序,只需稍加修改:安装“peach”或“pmap”gems,然后将
项更改为
项。peach(n)
(并行),其中
n
是线程数。每个CPU核心至少需要一个线程,但如果将I/O放入循环中,则需要更多线程

另外,使用Nokogiri,速度要快得多。问一问