Nutch是一个优秀的开源的数据爬取框架,我们只需要简单的配置,就可以完成数据爬取,当然,Nutch里面也提供了很灵活的的插件机制,我们随时都可以对它进行二次开发,以满足我们的需求,本篇散仙,先来介绍下,如何在eclipse里面以local模式调试nutch,只有在eclipse里面把它弄清楚了,那么,我们学习起来,才会更加容易,因为,目前大多数人,使用nutch,都是基于命令行的操作,虽然很简单方便,但是想深入定制开发,就很困难,所以,散仙在本篇里,会介绍下nutch基本的调试,以及编译。

下面进入正题,我们先来看下基本的步骤。

序号 名称 描述 1 安装部署ant 编译nutch编码使用 2 下载nutch源码 必须步骤 3 在nutch源码根目录下,执行ant等待编译完成 构建nutch 4 配置nutch-site.xml 必须步骤 5 ant eclipse 构建eclipse项目 导入eclipse中,调试 6 conf目录置顶 nutch加载时,会读取配置文件 7 执行org.apache.nutch.crawl.Injector注入种子 local调试 8 执行org.apache.nutch.crawl.Generator生成一个抓取列表 local调试 9 执行org.apache.nutch.fetcher.Fetcher生成一个抓取队列 local调试 10 执行org.apache.nutch.parse.ParseSegment执行contet生一个段文件 local调试 11 配置好solr服务 检索服务查询 12 执行org.apache.nutch.indexer.IndexingJob映射solr索引 local调试 13 映射完成后,就可以solr里面执行查询了 校验结果

编译完,导入eclipse的中如下图所示,注意conf文件夹置顶:


nutch-site.xml里面的配置如下:

Xml代码  
  1. <?xml version="1.0"?>
  2. <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
  3. <!-- Put site-specific property overrides in this file. -->
  4. <configuration>
  5. <property>
  6. <name>http.agent.name</name>
  7. <value>mynutch</value>
  8. </property>
  9. <property>
  10. <name>http.robots.agents</name>
  11. <value>*</value>
  12. <description>The agent strings we'll look for in robots.txt files,
  13. comma-separated, in decreasing order of precedence. You should
  14. put the value of http.agent.name as the first agent name, and keep the
  15. default * at the end of the list. E.g.: BlurflDev,Blurfl,*
  16. </description>
  17. </property>
  18. <property>
  19. <name>plugin.folders</name>
  20. <value>./src/plugin</value>
  21. <description>Directories where nutch plugins are located.  Each
  22. element may be a relative or absolute path.  If absolute, it is used
  23. as is.  If relative, it is searched for on the classpath.</description>
  24. </property>
  25. </configuration>
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?><!-- Put site-specific property overrides in this file. --><configuration><property><name>http.agent.name</name><value>mynutch</value>
</property><property><name>http.robots.agents</name><value>*</value><description>The agent strings we'll look for in robots.txt files,comma-separated, in decreasing order of precedence. You shouldput the value of http.agent.name as the first agent name, and keep thedefault * at the end of the list. E.g.: BlurflDev,Blurfl,*</description>
</property><property><name>plugin.folders</name><value>./src/plugin</value><description>Directories where nutch plugins are located.  Eachelement may be a relative or absolute path.  If absolute, it is usedas is.  If relative, it is searched for on the classpath.</description>
</property></configuration>

下面简单介绍下,在各个类里运行,需要做的一些改动,首先运行nutch,是基于Hadoop的local模式调试的,所以,你得改变下hadoop的权限,否则在运行过程中,会报错。散仙在这里提供一个简单的方法,拷贝hadoop的FileUtils类进行eclipse中,修改它的权限校验即可,如果你是在linux上运行,就不需要考虑这个问题了。

在开始调试之前,你需要在项目的根目录下建一个urls文件夹,并新建一个种子文件放入你要抓取的网址。

在Injector类里面,run方法里,改成

Java代码  
  1. public int run(String[] args) throws Exception {
  2. //    if (args.length < 2) {
  3. //      System.err.println("Usage: Injector <crawldb> <url_dir>");
  4. //      return -1;
  5. //    }
  6. args=new String[]{"mydir","urls"};//urls
  7. try {
  8. inject(new Path(args[0]), new Path(args[1]));
  9. return 0;
  10. } catch (Exception e) {
  11. LOG.error("Injector: " + StringUtils.stringifyException(e));
  12. return -1;
  13. }
  14. }
  public int run(String[] args) throws Exception {
//    if (args.length < 2) {
//      System.err.println("Usage: Injector <crawldb> <url_dir>");
//      return -1;
//    }args=new String[]{"mydir","urls"};//urlstry {inject(new Path(args[0]), new Path(args[1]));return 0;} catch (Exception e) {LOG.error("Injector: " + StringUtils.stringifyException(e));return -1;}}

在Generator里面的run方法改成

Java代码  
  1. public int run(String[] args) throws Exception {
  2. //    if (args.length < 2) {
  3. //      System.out
  4. //          .println("Usage: Generator <crawldb> <segments_dir> [-force] [-topN N] [-numFetchers numFetchers] [-adddays numDays] [-noFilter] [-noNorm][-maxNumSegments num]");
  5. //      return -1;
  6. //    }
  7. args=new String[]{"mydir","myseg","6","7",""};
  8. Path dbDir = new Path(args[0]);
  9. Path segmentsDir = new Path(args[1]);
  10. long curTime = System.currentTimeMillis();
  11. long topN = Long.MAX_VALUE;
  12. int numFetchers = -1;
  13. boolean filter = true;
  14. boolean norm = true;
  15. boolean force = false;
  16. int maxNumSegments = 1;
  17. for (int i = 2; i < args.length; i++) {
  18. if ("-topN".equals(args[i])) {
  19. topN = Long.parseLong(args[i + 1]);
  20. i++;
  21. } else if ("-numFetchers".equals(args[i])) {
  22. numFetchers = Integer.parseInt(args[i + 1]);
  23. i++;
  24. } else if ("-adddays".equals(args[i])) {
  25. long numDays = Integer.parseInt(args[i + 1]);
  26. curTime += numDays * 1000L * 60 * 60 * 24;
  27. } else if ("-noFilter".equals(args[i])) {
  28. filter = false;
  29. } else if ("-noNorm".equals(args[i])) {
  30. norm = false;
  31. } else if ("-force".equals(args[i])) {
  32. force = true;
  33. } else if ("-maxNumSegments".equals(args[i])) {
  34. maxNumSegments = Integer.parseInt(args[i + 1]);
  35. }
  36. }
  37. try {
  38. Path[] segs = generate(dbDir, segmentsDir, numFetchers, topN, curTime, filter,
  39. norm, force, maxNumSegments);
  40. if (segs == null) return -1;
  41. } catch (Exception e) {
  42. LOG.error("Generator: " + StringUtils.stringifyException(e));
  43. return -1;
  44. }
  45. return 0;
  46. }
public int run(String[] args) throws Exception {
//    if (args.length < 2) {
//      System.out
//          .println("Usage: Generator <crawldb> <segments_dir> [-force] [-topN N] [-numFetchers numFetchers] [-adddays numDays] [-noFilter] [-noNorm][-maxNumSegments num]");
//      return -1;
//    }args=new String[]{"mydir","myseg","6","7",""};Path dbDir = new Path(args[0]);Path segmentsDir = new Path(args[1]);long curTime = System.currentTimeMillis();long topN = Long.MAX_VALUE;int numFetchers = -1;boolean filter = true;boolean norm = true;boolean force = false;int maxNumSegments = 1;for (int i = 2; i < args.length; i++) {if ("-topN".equals(args[i])) {topN = Long.parseLong(args[i + 1]);i++;} else if ("-numFetchers".equals(args[i])) {numFetchers = Integer.parseInt(args[i + 1]);i++;} else if ("-adddays".equals(args[i])) {long numDays = Integer.parseInt(args[i + 1]);curTime += numDays * 1000L * 60 * 60 * 24;} else if ("-noFilter".equals(args[i])) {filter = false;} else if ("-noNorm".equals(args[i])) {norm = false;} else if ("-force".equals(args[i])) {force = true;} else if ("-maxNumSegments".equals(args[i])) {maxNumSegments = Integer.parseInt(args[i + 1]);}}try {Path[] segs = generate(dbDir, segmentsDir, numFetchers, topN, curTime, filter,norm, force, maxNumSegments);if (segs == null) return -1;} catch (Exception e) {LOG.error("Generator: " + StringUtils.stringifyException(e));return -1;}return 0;}

在Fetcher的run方法里面改动:

Java代码  
  1. public int run(String[] args) throws Exception {
  2. String usage = "Usage: Fetcher <segment> [-threads n]";
  3. args=new String[]{"D:\\20140520nutchplugin\\apache-nutch-1.8\\myseg\\20140520120541","4"};
  4. //    if (args.length < 1) {
  5. //      System.err.println(usage);
  6. //      return -1;
  7. //    }
  8. Path segment = new Path(args[0]);
  9. int threads = getConf().getInt("fetcher.threads.fetch", 10);
  10. boolean parsing = false;
  11. for (int i = 1; i < args.length; i++) {       // parse command line
  12. if (args[i].equals("-threads")) {           // found -threads option
  13. threads =  Integer.parseInt(args[++i]);
  14. }
  15. }
  16. getConf().setInt("fetcher.threads.fetch", threads);
  17. try {
  18. fetch(segment, threads);
  19. return 0;
  20. } catch (Exception e) {
  21. LOG.error("Fetcher: " + StringUtils.stringifyException(e));
  22. return -1;
  23. }
  24. }
  public int run(String[] args) throws Exception {String usage = "Usage: Fetcher <segment> [-threads n]";args=new String[]{"D:\\20140520nutchplugin\\apache-nutch-1.8\\myseg\\20140520120541","4"};
//    if (args.length < 1) {
//      System.err.println(usage);
//      return -1;
//    }Path segment = new Path(args[0]);int threads = getConf().getInt("fetcher.threads.fetch", 10);boolean parsing = false;for (int i = 1; i < args.length; i++) {       // parse command lineif (args[i].equals("-threads")) {           // found -threads optionthreads =  Integer.parseInt(args[++i]);}}getConf().setInt("fetcher.threads.fetch", threads);try {fetch(segment, threads);return 0;} catch (Exception e) {LOG.error("Fetcher: " + StringUtils.stringifyException(e));return -1;}}

在ParseSegment里面的run方法改动:

Java代码  
  1. public int run(String[] args) throws Exception {
  2. Path segment;
  3. String usage = "Usage: ParseSegment segment [-noFilter] [-noNormalize]";
  4. //    if (args.length == 0) {
  5. //      System.err.println(usage);
  6. //      System.exit(-1);
  7. //    }
  8. args=new String[]{"D:\\20140520nutchplugin\\apache-nutch-1.8\\myseg\\20140520120541"};
  9. if(args.length > 1) {
  10. for(int i = 1; i < args.length; i++) {
  11. String param = args[i];
  12. if("-nofilter".equalsIgnoreCase(param)) {
  13. getConf().setBoolean("parse.filter.urls", false);
  14. } else if ("-nonormalize".equalsIgnoreCase(param)) {
  15. getConf().setBoolean("parse.normalize.urls", false);
  16. }
  17. }
  18. }
  19. segment = new Path(args[0]);
  20. parse(segment);
  21. return 0;
  22. }
 public int run(String[] args) throws Exception {Path segment;String usage = "Usage: ParseSegment segment [-noFilter] [-noNormalize]";//    if (args.length == 0) {
//      System.err.println(usage);
//      System.exit(-1);
//    }args=new String[]{"D:\\20140520nutchplugin\\apache-nutch-1.8\\myseg\\20140520120541"};if(args.length > 1) {for(int i = 1; i < args.length; i++) {String param = args[i];if("-nofilter".equalsIgnoreCase(param)) {getConf().setBoolean("parse.filter.urls", false);} else if ("-nonormalize".equalsIgnoreCase(param)) {getConf().setBoolean("parse.normalize.urls", false);}}}segment = new Path(args[0]);parse(segment);return 0;}

在IndexingJob的run方法里面改动:

Java代码  
  1. public int run(String[] args) throws Exception {
  2. args=new String[]{"mydir","D:\\20140520nutchplugin\\apache-nutch-1.8\\myseg\\20140520120541"};
  3. if (args.length < 2) {
  4. System.err
  5. .println("Usage: Indexer <crawldb> [-linkdb <linkdb>] [-params k1=v1&k2=v2...] (<segment> ... | -dir <segments>) [-noCommit] [-deleteGone] [-filter] [-normalize]");
  6. IndexWriters writers = new IndexWriters(getConf());
  7. System.err.println(writers.describe());
  8. return -1;
  9. }
  10. final Path crawlDb = new Path(args[0]);
  11. Path linkDb = null;
  12. final List<Path> segments = new ArrayList<Path>();
  13. String params = null;
  14. boolean noCommit = false;
  15. boolean deleteGone = false;
  16. boolean filter = false;
  17. boolean normalize = false;
  18. for (int i = 1; i < args.length; i++) {
  19. if (args[i].equals("-linkdb")) {
  20. linkDb = new Path(args[++i]);
  21. } else if (args[i].equals("-dir")) {
  22. Path dir = new Path(args[++i]);
  23. FileSystem fs = dir.getFileSystem(getConf());
  24. FileStatus[] fstats = fs.listStatus(dir,
  25. HadoopFSUtil.getPassDirectoriesFilter(fs));
  26. Path[] files = HadoopFSUtil.getPaths(fstats);
  27. for (Path p : files) {
  28. segments.add(p);
  29. }
  30. } else if (args[i].equals("-noCommit")) {
  31. noCommit = true;
  32. } else if (args[i].equals("-deleteGone")) {
  33. deleteGone = true;
  34. } else if (args[i].equals("-filter")) {
  35. filter = true;
  36. } else if (args[i].equals("-normalize")) {
  37. normalize = true;
  38. } else if (args[i].equals("-params")) {
  39. params = args[++i];
  40. } else {
  41. segments.add(new Path(args[i]));
  42. }
  43. }
  44. try {
  45. index(crawlDb, linkDb, segments, noCommit, deleteGone, params,
  46. filter, normalize);
  47. return 0;
  48. } catch (final Exception e) {
  49. LOG.error("Indexer: " + StringUtils.stringifyException(e));
  50. return -1;
  51. }
  52. }
  public int run(String[] args) throws Exception {args=new String[]{"mydir","D:\\20140520nutchplugin\\apache-nutch-1.8\\myseg\\20140520120541"};if (args.length < 2) {System.err.println("Usage: Indexer <crawldb> [-linkdb <linkdb>] [-params k1=v1&k2=v2...] (<segment> ... | -dir <segments>) [-noCommit] [-deleteGone] [-filter] [-normalize]");IndexWriters writers = new IndexWriters(getConf());System.err.println(writers.describe());return -1;}final Path crawlDb = new Path(args[0]);Path linkDb = null;final List<Path> segments = new ArrayList<Path>();String params = null;boolean noCommit = false;boolean deleteGone = false;boolean filter = false;boolean normalize = false;for (int i = 1; i < args.length; i++) {if (args[i].equals("-linkdb")) {linkDb = new Path(args[++i]);} else if (args[i].equals("-dir")) {Path dir = new Path(args[++i]);FileSystem fs = dir.getFileSystem(getConf());FileStatus[] fstats = fs.listStatus(dir,HadoopFSUtil.getPassDirectoriesFilter(fs));Path[] files = HadoopFSUtil.getPaths(fstats);for (Path p : files) {segments.add(p);}} else if (args[i].equals("-noCommit")) {noCommit = true;} else if (args[i].equals("-deleteGone")) {deleteGone = true;} else if (args[i].equals("-filter")) {filter = true;} else if (args[i].equals("-normalize")) {normalize = true;} else if (args[i].equals("-params")) {params = args[++i];} else {segments.add(new Path(args[i]));}}try {index(crawlDb, linkDb, segments, noCommit, deleteGone, params,filter, normalize);return 0;} catch (final Exception e) {LOG.error("Indexer: " + StringUtils.stringifyException(e));return -1;}}

除此之外,还需要,在SolrIndexWriter的187行和SolrUtils的54行分别添加如下代码,修改solr的映射地址:

Java代码  
  1. String serverURL = conf.get(SolrConstants.SERVER_URL);
  2. serverURL="http://localhost:8983/solr/";
String serverURL = conf.get(SolrConstants.SERVER_URL);serverURL="http://localhost:8983/solr/";
Java代码  
  1. // String serverURL = job.get(SolrConstants.SERVER_URL);
  2. String serverURL ="http://localhost:8983/solr";
// String serverURL = job.get(SolrConstants.SERVER_URL);String serverURL ="http://localhost:8983/solr";

按上面几个步骤,每执行一个类的时候,就修改其的运行参数,因为nutch的作业具有依赖性,这一个作业的输入,往往是上一个作业的输出,手动依次运行修改上面的5个类,最终我们的索引就可以生成在solr里,截图如下:

当然,我们还可以,配置分词策略,来使我们检索更加通用,准确.

Nutch是一个优秀的开源的数据爬取框架相关推荐

  1. 打造轻量级可视化数据爬取工具-菩提

    作者:jiaqiangwang,腾讯 IEG 后台开发工程师 背景 在大数据及机器学习日益火爆的今天,数据作为基石发挥了至关重要的作用.网页内容爬取作为数据的一个重要补充来源,数据爬取开发成了一个必不 ...

  2. python爬取软件内数据_各种数据爬取工具爬虫合集整理

    却道天凉好个秋~ 不用编程敲代码的爬取数据的工具合集,简单上手易用的爬虫脚本工具软件汇总 1.工具软件类: Microsoft Excel excel也可以爬一些规整的表格数据等,没想到吧! 八爪鱼 ...

  3. 使用python进行股票数据爬取中的时间限制和策略

    股票数据爬取中的时间限制和策略 在进行股票数据爬取时,时间限制和策略是非常重要的考虑因素.本文将介绍两个与此相关的函数:is_trade_day()和stock_work_day(). is_trad ...

  4. python数据爬取、分析与内容审核基于PaddlePaddle

    这次要做的就是分四步完成爬取评论数据并进行可视化的评论内容分析.先展示一下预期效果 第一步:爱奇艺<青春有你2>评论数据爬取(参考链接:https://www.iqiyi.com/v_19 ...

  5. python数据爬取---爬取文本数据并进行特征提取_python 域名提取

    初识Scrapy 为什么使用Scrapy? 我们可以用requests和beautifulsoup完成一个实用的爬虫,但如果想大规模爬取的话,我们需要学习Scrapy这个优秀Python框架,学习它的 ...

  6. 精准数据爬取(精抽取)的爬虫选择问题

    有些人问,开发网络爬虫应该选择Nutch.Crawler4j.WebMagic.scrapy.WebCollector还是其他的?这里按照我的经验随便扯淡一下:上面说的爬虫,基本可以分3类:1.分布式 ...

  7. 网络爬虫分析实例:基于音悦台网站榜单的数据爬取与分析

    基于音悦台网站榜单的数据爬取与分析 本实验代码:进入 一.研究背景 在互联网发展初期,网站相对较少,信息查找比较容易.然而伴随互联网爆炸性的发展,普通网络用户想找到所需的资料简直如同大海捞针,这时为满 ...

  8. stockgo数据爬取-业绩预告

    一.爬虫目标 本次爬虫程序的主要目标有: 1.每日自动爬取股票业绩预告(包括年报.一季报.中报.三季报); 2.爬取历史数据; 3.每日自动增量更新,免人工维护; 4.业绩预告分类分级,按照行业,概念 ...

  9. Python之数据爬取数据可视化

    前言 临近中秋,月饼的销量持续增长,然而不仅仅是中秋节,非旺季也有很多月饼爱好者在电商平台购买月饼.本文利用淘宝上的公开数据,应用 python 对月饼非旺季的销售状况进行分析,并对统计结果进行数据可 ...

  10. Python网络数据爬取及分析-智联招聘

    python网络数据爬取及分析-智联招聘 一. 数据爬取 智联招聘是一家面向大型公司和快速发展的中小企业提供一站式专业人力资源的公司,可在智联招聘网站上根据不同城市.不同职位需求搜索得到相关招聘信息. ...

最新文章

  1. Python 刷英语六级段落匹配仅需 3 秒?
  2. 2021年5G发展展望
  3. linux系统管理学习笔记之一-------linux解压缩命令
  4. visio取消首字母大写
  5. 学习SAP项目成功实施的十大条件
  6. 通过IP地址查计算机名
  7. java支持接口吗_java – 支持专用接口方法
  8. 断面计算土方excel表_Civil 3D工程量计算小技巧,一次打包给你!
  9. php 动态修改文本内容_九大编程语言优缺点第八期:PHP
  10. java中选择结构有哪些_Java中的选择结构
  11. SaaS产品服务进行网络推广的必要性
  12. teamviewer超时后连接被阻断。您的许可证对您与伙伴的最大话时间有所限制
  13. 初创公司几个投资人,各占多少股份合适?
  14. 【题解】【AcWing】1564. 哈希
  15. 程序员优秀开源免费软件推荐
  16. 学习Python后能找什么工作
  17. excel取消工作表保护,获取原始密码
  18. CAM350导入rou文件
  19. 大神之路-起始篇 | 第18章.计算机科学导论之【人工智能】学习笔记...
  20. 运用jQuery动态向html中添加表格元素

热门文章

  1. websockets_将WebSockets与Node.js结合使用
  2. 基于Keras+YOLOv3的口罩佩戴情况检测系统【超详细!!!保姆级教程】
  3. Android SoundPool封装
  4. android dff播放器,无损音乐文件的整理(dff、dsf篇)
  5. 开源ext2read代码走读之-ext2文件系统中的超级块及对应代码
  6. 中兴网络设备交换机路由器查看ARP表项命令方法
  7. 互补滤波算法及理论推导
  8. python整人小代码_整人代码大全
  9. 元宇宙的时代来不及解释了快上车
  10. f分布表完整图a=0.01_R语言具有Student-t分布改进的GARCH(1,1)模型的贝叶斯估计...