我有一个非常简单的格式化XML文档,我想将其转换为适合导入Hive的TSV。这份文件的格式很简单:
<root>
<row>
<ID>0</ID>
<ParentID>0</ParentID>
<Url></Url>
<Title></Title>
<Text></Text>
<Username></Username>
<Points>0</Points>
<Type>0</Type>
<Timestamp></Timestamp>
<CommentCount>0</CommentCount>
</row>
</root>
我有一个可用的Ruby脚本,可以将上面格式化的文档正确地转换为TSV。就在这里:
require "rubygems"
require "crack"
xml = Crack::XML.parse(File.read("sample.xml"))
xml['root']['row'].each{ |i|
puts "#{i['ID']} #{i['ParentID']} #{i['Url']} #{i['Title']}..."
}
不幸的是,我需要翻译的文件比这个脚本可以处理的文件大得多(> 1 GB)。
Hadoop的用武之地。最简单的解决方案可能是用Java编写MapReduce作业,但鉴于我缺乏Java技能,这不是一个选择。所以我想在Python或Ruby中编写一个mapper脚本,我远非专家,但至少可以导航。
我的计划是做以下事情:
然而,这种方法一直失败。我使用了各种Ruby / Wukong脚本但没有成功。这是一篇基于文章here的文章:
#!/usr/bin/env ruby
require 'rubygems'
require 'crack'
xml = nil
STDIN.each_line do |line|
puts |line|
line.strip!
if line.include?("<row")
xml = Crack::XML.parse(line)
xml['root']['row'].each{ |i|
puts "#{i['ID']} #{i['ParentID']} #{i['Url']}..."
else
puts 'no line'
end
if line.include?("</root>")
puts 'EOF'
end
end
此工作和其他工作失败如下:
hadoop jar /usr/lib/hadoop-0.20/contrib/streaming/hadoop-streaming-0.20.2+737.jar -input /hackernews/Datasets/sample.xml -output out -mapper mapper.rb -inputreader "StreamXmlRecordReader,begin=<row,end=</row>"
packageJobJar: [/var/lib/hadoop-0.20/cache/sog/hadoop-unjar1519776523448982201/] [] /tmp/streamjob2858887307771024146.jar tmpDir=null
11/01/14 17:29:17 INFO mapred.FileInputFormat: Total input paths to process : 1
11/01/14 17:29:17 INFO streaming.StreamJob: getLocalDirs(): [/var/lib/hadoop-0.20/cache/sog/mapred/local]
11/01/14 17:29:17 INFO streaming.StreamJob: Running job: job_201101141647_0001
11/01/14 17:29:17 INFO streaming.StreamJob: To kill this job, run:
11/01/14 17:29:17 INFO streaming.StreamJob: /usr/lib/hadoop-0.20/bin/hadoop job -Dmapred.job.tracker=localhost:8021 -kill job_201101141647_0001
11/01/14 17:29:17 INFO streaming.StreamJob: Tracking URL: http://localhost:50030/jobdetails.jsp?jobid=job_201101141647_0001
11/01/14 17:29:18 INFO streaming.StreamJob: map 0% reduce 0%
11/01/14 17:30:05 INFO streaming.StreamJob: map 100% reduce 100%
11/01/14 17:30:05 INFO streaming.StreamJob: To kill this job, run:
11/01/14 17:30:05 INFO streaming.StreamJob: /usr/lib/hadoop-0.20/bin/hadoop job -Dmapred.job.tracker=localhost:8021 -kill job_201101141647_0001
11/01/14 17:30:05 INFO streaming.StreamJob: Tracking URL: http://localhost:50030/jobdetails.jsp?jobid=job_201101141647_0001
11/01/14 17:30:05 ERROR streaming.StreamJob: Job not Successful!
11/01/14 17:30:05 INFO streaming.StreamJob: killJob...
Streaming Command Failed!
第一个问题是我无法分辨我失败的地方:我的脚本或StreamXmlRecordReader。
第二个问题是,一位亲切而乐于助人的专家告诉我,因为StreamXmlRecordReader没有产生额外的记录分隔符,这种方法可能不会起作用,而且我需要单一阅读行,grep for row,堆叠所有内容,直到你得到/ row,然后解析它。
这是最简单的方法,如果是这样,我最好如何做到这一点?
性能不是一个大问题,因为这些文件每隔几周左右就会批量处理,以防万一。
答案 0 :(得分:1)
如果你遇到这个问题,那么Infochimps的人们就解决了这个问题。这是必要的悟空剧本:
http://thedatachef.blogspot.com/2011/01/processing-xml-records-with-hadoop-and.html
答案 1 :(得分:0)
一个常常的错误就是没有脚本的执行权限“chmod a + x mapper.rb”试一试。
查看您的工作跟踪器日志以明确获取错误。您还可以从http://namenode:50030/jobtracker.jsp点击失败的作业,然后在地图上的“失败/被杀死的任务尝试”中的“失败”中获取信息。
此外,当您运行流作业时,在选项行上放置“-verbose”,可能会提供更多信息。