2016-10-20 5 views
2

저는 Typhoeus를 사용하여 zip 파일을 메모리로 스트리밍 한 다음 각 파일을 반복하여 XML 문서를 추출했습니다. Nokogiri를 사용했지만 오류가 발생하는 XML 파일을 읽으려면 Errno::ENOENT: No such file or directory @ rb_sysopen - my_xml_doc.xml.다운로드 한 zip 파일에서 XML 문서를 가져 오는 방법

오류를 찾아 보니 루비가 틀린 디렉토리에서 스크립트를 실행할 가능성이 가장 높습니다. 좀 혼란 스럽지만 XML 문서를 메모리에 저장해야만 읽을 수 있습니다. 여기

더 명확하게 내 코드입니다 :

컨트롤러

def index 
    url = "http://feed.omgili.com/5Rh5AMTrc4Pv/mainstream/posts/" 
    html_response = Typhoeus.get(url) 
    doc = Nokogiri::HTML(html_response.response_body) 

    path_array = [] 
    doc.search("a").each do |value| 
    path_array << value.content if value.content.include?(".zip") 
    end 

    path_array.each do |zip_link| 
    download_file = File.open zip_link, "wb" 
    request = Typhoeus::Request.new("#{url}#{zip_link}") 
    binding.pry 

    request.on_headers do |response| 
     if response.code != 200 
     raise "Request failed" 
     end 
    end 

    request.on_body do |chunk| 
     download_file.write(chunk) 
    end 

    request.run 

    Zip::File.open(download_file) do |zipfile| 
     zipfile.each do |file| 
     binding.pry 
     doc = Nokogiri::XML(File.read(file.name)) 
     end 
    end 
    end 

end 

파일

=> #<Zip::Entry:0x007ff88998373 
@comment="", 
@comment_length=0, 
@compressed_size=49626, 
@compression_method=8, 
@crc=20393847, 
@dirty=false, 
@external_file_attributes=0, 
@extra={}, 
@extra_length=0, 
@filepath=nil, 
@follow_symlinks=false, 
@fstype=0, 
@ftype=:file, 
@gp_flags=2056, 
@header_signature=009890, 
@internal_file_attributes=0, 
@last_mod_date=18769, 
@last_mod_time=32626, 
@local_header_offset=0, 
@local_header_size=nil, 
@name="my_xml_doc.xml", 
@name_length=36, 
@restore_ownership=false, 
@restore_permissions=false, 
@restore_times=true, 
@size=138793, 
@time=2016-10-17 15:59:36 -0400, 
@unix_gid=nil, 
@unix_perms=nil, 
@unix_uid=nil, 
@version=20, 
@version_needed_to_extract=20, 
@zipfile="some_zip_file.zip"> 
+1

는 항상 이러한 XML 파일의 크기 범위가 될 것 무엇을 알고 있는가? 그렇지 않다면 디스크를 조작하기 전에 디스크에 저장하는 것이 좋습니다. –

+0

크기를 항상 알 수는 없지만 제안 해 주셔서 감사합니다! 궁극적으로 XML을 Redis 목록에 직접 넣을 것입니다. (코드에서 아직까지는 그 사실을 알지 못했습니다.) – Ctpelnar1988

답변

0

이 내가 생각 해낸 해결책입니다 :

개 보석 :

gem 'typhoeus' 
gem 'rubyzip' 
gem 'redis', '~>3.2' 

컨트롤러 :

def xml_to_redis_list(url) 
    html_response = Typhoeus.get(url) 
    doc = Nokogiri::HTML(html_response.response_body) 
    @redis = Redis.new 

    path_array = [] 
    doc.search("a").each do |value| 
    path_array << value.content if value.content.include?(".zip") 
    end 

    path_array.each do |zip_link| 
    download_file = File.open zip_link, "wb" 
    request = Typhoeus::Request.new("#{url}#{zip_link}") 

    request.on_headers do |response| 
     if response.code != 200 
     raise "Request failed" 
     end 
    end 

    request.on_body do |chunk| 
     download_file.write(chunk) 
    end 

    request.run 

    while download_file.size == 0 
     sleep 1 
    end 

    zip_download = Zip::File.open(download_file.path) 
    Zip::File.open("#{Rails.root}/#{zip_download.name}") do |zip_file| 
     zip_file.each do |file| 
     xml_string = zip_file.read(file.name) 
     check_if_xml_duplicate(xml_string) 
     @redis.rpush("NEWS_XML", xml_string) 
     end 
    end 
    File.delete("#{Rails.root}/#{zip_link}") 
    end 

end 

def check_if_xml_duplicate(xml_string) 
    @redis.lrem("NEWS_XML", -1, xml_string) 
end 
관련 문제