2

Hive へのインポートに適した TSV に変換したい、非常に単純な形式の XML ドキュメントがあります。このドキュメントのフォーマットは単純です。

<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>

上記のようにフォーマットされたドキュメントを TSV に適切に変換する作業中の Ruby スクリプトがあります。それはここにあります:

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のいずれかでマッパースクリプトを書きたかったのですが、私は専門家とはほど遠いですが、少なくともナビゲートすることはできます.

私の計画は、次のことを行うことでした。

  1. StreamXmlRecordReader を使用してファイル レコードをレコードごとに解析する
  2. クラックを使用してデシリアライゼーションをマップする
  3. タブで区切られた要素の単純な逆流でそれを減らします

しかし、このアプローチは一貫して失敗しています。さまざまな Ruby/Wukong スクリプトを使用しましたが、成功しませんでした。これは、ここの記事に基づいたものです。

#!/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 なのか。

2 番目の問題は、親切で親切な専門家から、StreamXmlRecordReader は追加のレコード区切り文字を生成しないため、このアプローチはおそらくうまくいかず、1 行で読み取る必要があると言われたことです。grep行の場合、/行が得られるまですべてを積み上げてから解析します。

これは最も簡単なアプローチですか? もしそうなら、どうすればそれを達成するのが最善でしょうか?

念のため、これらのファイルは数週間ごとにバッチ処理されるため、パフォーマンスは大きな問題ではありません。

4

2 に答える 2

1

あなたがこの問題を抱えているなら、Infochimpsの人々はそれを解決しました。必要なWukongスクリプトは次のとおりです。

http://thedatachef.blogspot.com/2011/01/processing-xml-records-with-hadoop-and.html

于 2011-01-17T21:10:18.337 に答える
0

よくある間違いの1つは、スクリプト「chmod a +xmapper.rb」に実行権限がないことです。試してみてください。

特にエラーを取得するには、ジョブトラッカーログを確認してください。http:// namenode:50030 / jobtracker.jspから情報を取得することもできます。失敗したジョブをクリックしてから、マップの「Failed /KilledTaskAttempts」の「Failed」をクリックします。

また、ストリームジョブを実行するときは、オプション行に「-verbose」を入力すると、さらに情報が得られる可能性があります。

于 2011-01-17T02:23:48.900 に答える