HDFS (Hadoop Distributed FileSystem) Writer for Heritrix 3 This file is part of the Heritrix web crawler (crawler.archive.org). Heritrix is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser Public License as published by the Free Software Foundation; either version 2.1 of the License, or any later version. Heritrix is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Public License for more details. You should have received a copy of the GNU Lesser Public License along with Heritrix; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contributors: Doug Judd Zvents, Inc. doug at zvents.com Greg Lu OpenPlaces.Org greg.lu at gmail.com Zach Bailey Dataclip.com znbailey at gmail.com TABLE OF CONTENTS ================= * SETUP * CONFIGURING HERITRIX * FILE FORMAT * COMPILING THE SOURCE * RUNNING AN EXAMPLE MAP-REDUCE PROGRAM * HELPFUL HINTS The heritrix-hadoop-dfs-writer-processor is an extension to the Heritrix open source crawler written by the Internet Archive (http://crawler.archive.org/) that enables it to store crawled content directly into HDFS, the Hadoop Distributed FileSystem (http://lucene.apache.org/hadoop/). Hadoop implements the Map/Reduce distributed computation framework on top of HDFS. heritrix-hadoop-dfs-writer-processor writes crawled content into SequenceFile format which is directly supported by the Map/Reduce framework and has support for compression. This facilitates running high-speed, distributed computations over content crawled with Heritrix. This version of heritrix-hadoop-dfs-writer-processor assumes version 3.0 of Heritrix and version 0.20.1+ of Hadoop. Newer versions of Hadoop and Heritrix may continue to work with this connector as long as the pertinent APIs have not changed. Just replace the jar files with the newer versions. SETUP ===== 1. Start hadoop/hdfs 2. Install heritrix 3. Untar the current distribution to any directory and once its untarred enter the <HDFSWriterProcessor_home> directory and run "ant jar". 4. Copy the following jar files from the heritrix-hadoop-dfs-writer-processor binary distribution into the lib/ directory of your Heritrix installation: a) heritrix-hadoop-dfs-writer-processor-*.jar b) hadoop-*-core.jar c) log4j-*.jar 5. Start Heritrix CONFIGURING HERITRIX ==================== Heritrix 3 now uses a spring configuration format for configuring the processor beans. This quick section assumes you're familiar with the basics of Spring and its XML configuration facilities. First, declare your HDFSParameters bean: <bean id="hdfsParameters" class="org.archive.io.hdfs.HDFSParameters"> <!-- each file written is prefixed with this string (required) --> <property name="prefix" value="CrawlData"/> <!-- URL for the HDFS name node, not required, default is hdfs://localhost:9000 --> <property name="hdfsFsDefaultName" value="hdfs://localhost:9000" /> <!-- where to write the files to, not required, default is "/crawl" --> <property name="hdfsOutputPath" value="/crawl/" /> <!-- one of "NONE", "RECORD", "BLOCK", "DEFAULT" (delegates to HDFS sequence file configuration) see org.apache.hadoop.io.SequenceFile.CompressionType --> <property name="hdfsCompressionType" value="NONE" /> </bean> Then, declare the processor bean itself: <bean id="hdfsWriterProcessor" class="org.archive.modules.writer.HDFSWriterProcessor"> <property name="hdfsParameters" ref="hdfsParameters"/> </bean> Finally, inject this bean into the DispositionChain: <bean id="dispositionProcessors" class="org.archive.modules.DispositionChain"> <property name="processors"> <list> <ref bean="hdfsWriterProcessor"/> ... MORE BEANS HERE ... </list> </property> </bean> FILE FORMAT =========== Crawl results are stored in the SequenceFile format which is a series of optionally compressed, key-value documents. Both the key and value of each document is type org.apache.hadoop.io.Text. Almost all of the time you're going to read these SequenceFiles as part of a map/reduce job, so it's strongly recommended that you use the HDFSWriterDocument class to read the value of each document in your map function like so: public void map(Text uri, Text docText, OutputCollector<Text, LongWritable> collector, Reporter reporter) throws IOException { HDFSWriterDocument hdfsDoc = new HDFSWriterDocument(); hdfsDoc.readFields(new DataInputStream(new ByteArrayInputStream(docText.getBytes()))); //access the document data using hdfsDoc //here, we emit the charset and a value of 1 for present: String charset = hdfsDoc.getCharset(); if (charset != null) { collector.collect(new Text(charset), new LongWritable(1L)); } } ADVANCED INFORMATION Note again that HDFSWriterDocument handles reading the data from the low-level format so this may not be that useful, but we'll document it anyway in case you want to write a parser in another language: HDFSWriter/0.3 <name-value-parameters> CRLF <http-request> (only for http scheme) CRLF <http-response-headers> (only for http scheme) CRLF <response-body> The following example, illustrates the format: HDFSWriter/0.3 URL: http://www.cnn.com/.element/ssi/www/sect/1.3/misc/contextual/MAIN.html Ip-Address: 64.236.29.120 Crawl-Time: 20070123093916 Is-Seed: false Path-From-Seed: X Via: http://www.cnn.com/ GET /.element/ssi/www/sect/1.3/misc/contextual/MAIN.html HTTP/1.0 User-Agent: Mozilla/5.0 (compatible; heritrix/1.12.0 +http://www.zvents.com/) From: crawler@zvents.com Connection: close Referer: http://www.cnn.com/ Host: www.cnn.com Cookie: CNNid=46e19fc2-12419-1169545061-167 HTTP/1.1 200 OK Date: Tue, 23 Jan 2007 09:37:46 GMT Server: Apache Vary: Accept-Encoding,User-Agent Cache-Control: max-age=60, private Expires: Tue, 23 Jan 2007 09:38:46 GMT Content-Length: 3489 Content-Type: text/html Connection: close <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> <title>Link Spots CSI</title> <script type="text/javascript"> [...] The keys of the name-value-parameters can be controlled by setting the relevant property on the HDFSParameters bean in the spring configuration. For example: <bean id="hdfsParameters" class="org.archive.io.hdfs.HDFSParameters"> ... OTHER PROPERTIES ... <!-- default is "Seed-Url", let's change it to "seedUrl" --> <property name="seedUrlFieldName" value="seedUrl"/> </bean> The default names can be found by inspecting the HDFSParameters source. COMPILING THE SOURCE ==================== 1.) Fork the git repo 2.) Clone the git repo to your local machine 3.) run "ant jar" from the project root RUNNING AN EXAMPLE MAP-REDUCE PROGRAM ===================================== The binary and source distributions come with an example map-reduce program called com.example.mapred.CountCharsets that produces counts for all of the unique character encodings (charsets) encountered in your crawled documents. The source code for this example can be found in the file src/java/com/example/mapred/CountCharsets.java in the source distribution. To run this example program, do the following. 1. Copy the heritrix-hadoop-dfs-writer-processor-*.jar file into the lib/ directory of your hadoop installation. (NOTE: You should push this jar file into the lib directory of all participating Hadoop nodes) 2. cd into the hadoop directory 3. Invoke the map-reduce jobs with a line like the following: $ ./bin/hadoop com.example.mapred.CountCharsets \ /heritrix/crawls/no-extract-5-20070130081658484 /output (Be sure to change the second argument in the above line to where you told Heritrix to write the crawl data) This should generate a file in HDFS called /output/part-00000 that contains a number of lines, one for each unique character set encountered, containing the name of the character set followed a count. To see the result, run the following commands. $ ./bin/hadoop fs -text /output/part-00000
znbailey/heritrix-hdfs-writer
A Heritrix 3 writer processor for storing crawled data in the Hadoop Distributed File System
Java