You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Nutch爬取流程中拆分段落并导入Solr,添加位置与章节字段?

我来帮你搞定这个需求——要在Nutch爬取流程里实现段落拆分并带上位置和章节信息,核心是扩展Nutch的解析插件,把单文档拆成多个段落级的子文档再推给Solr。下面是一步步的具体实现方法:

1. 编写自定义解析过滤器插件

Nutch的解析阶段是通过插件扩展的,我们需要写一个ParseFilter实现类,来完成段落拆分、章节提取和元数据添加。

1.1 搭建插件目录结构

在Nutch源码的src/plugin下新建parse-paragraph目录,结构如下:

parse-paragraph/
├── build.xml
├── plugin.xml
└── src/
    └── main/
        └── java/
            └── com/
                └── yourdomain/
                    └── nutch/
                        └── parse/
                            └── ParagraphParseFilter.java

1.2 实现ParseFilter类

用Java编写核心逻辑,这里用Jsoup来解析HTML(方便提取h2和段落),示例代码如下:

import org.apache.hadoop.conf.Configuration;
import org.apache.nutch.parse.*;
import org.apache.nutch.metadata.Metadata;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.nio.charset.StandardCharsets;

public class ParagraphParseFilter implements ParseFilter {
    private Configuration conf;

    @Override
    public void setConf(Configuration conf) {
        this.conf = conf;
    }

    @Override
    public Configuration getConf() {
        return conf;
    }

    @Override
    public ParseResult filter(Content content, ParseResult parseResult, ParseContext parseContext) {
        ParseResult paragraphResults = new ParseResult();
        Parse originalParse = parseResult.get(content.getUrl());
        String htmlContent = new String(content.getContent(), StandardCharsets.UTF_8);

        // 用Jsoup解析HTML文档
        Document doc = Jsoup.parse(htmlContent);
        Elements allH2 = doc.select("h2");
        Elements allParagraphs = doc.select("p");

        int paragraphIndex = 1;
        String currentSection = "无章节"; // 默认章节名称

        // 遍历所有段落,生成段落级解析结果
        for (Element para : allParagraphs) {
            String paraText = para.text().trim();
            if (paraText.isEmpty()) continue;

            // 更新当前段落所属的最近h2章节
            for (Element h2 : allH2) {
                if (h2.isBefore(para) && (h2.nextElementSibling() == para || h2.nextElementSibling().isBefore(para))) {
                    currentSection = h2.text().trim();
                }
            }

            // 构建段落的元数据
            Metadata paraMeta = new Metadata();
            paraMeta.add("paragraph_position", String.valueOf(paragraphIndex));
            paraMeta.add("paragraph_section", currentSection);
            // 保留原文档的关键信息,方便关联
            paraMeta.add("original_url", content.getUrl());
            paraMeta.add("original_title", originalParse.getTitle());

            // 创建段落的Parse对象
            ParseText paraTextObj = new ParseText(paraText);
            Parse paraParse = new ParseImpl(paraTextObj, paraMeta);

            // 用原URL+段落索引作为唯一标识,添加到结果集
            String paraKey = content.getUrl() + "#para_" + paragraphIndex;
            paragraphResults.put(paraKey, paraParse);
            paragraphIndex++;
        }

        // 如果没有提取到段落,返回原解析结果(避免丢失数据)
        return paragraphResults.isEmpty() ? parseResult : paragraphResults;
    }
}

1.3 配置插件文件

  • plugin.xml:声明插件和依赖
<plugin id="parse-paragraph" name="Paragraph Parse Filter" version="1.0.0" provider-name="yourdomain.com">
    <runtime>
        <library name="parse-paragraph.jar"/>
        <!-- 引入jsoup依赖,确保jar包在插件的lib目录下 -->
        <library name="jsoup-1.17.2.jar"/>
    </runtime>
    <requires>
        <import plugin="nutch-extensionpoints"/>
        <import plugin="parse-api"/>
        <import plugin="parse-html"/>
    </requires>
    <extension id="com.yourdomain.nutch.parse.ParagraphParseFilter"
               name="Paragraph Parse Filter"
               point="org.apache.nutch.parse.ParseFilter">
        <implementation id="ParagraphParseFilter"
                        class="com.yourdomain.nutch.parse.ParagraphParseFilter"/>
    </extension>
</plugin>
  • build.xml:配置编译规则(参考其他解析插件的build.xml,确保能正确编译打包)

1.4 编译插件

把jsoup的jar包放到parse-paragraph/lib目录,然后在Nutch根目录执行:

ant clean runtime

这会把自定义插件编译并打包到runtime/local目录的插件文件夹里。

2. 配置Nutch启用自定义插件

编辑conf/nutch-site.xml,修改plugin.includes属性,加入你的自定义插件:

<property>
  <name>plugin.includes</name>
  <value>... parse-paragraph ...</value>
  <!-- 确保parse-paragraph在parse-html之后加载 -->
</property>
3. 调整Solr配置

3.1 修改Solr Schema

在Solr的nutch core的managed-schema(或schema.xml)里添加两个字段:

<field name="paragraph_position" type="int" indexed="true" stored="true"/>
<field name="paragraph_section" type="text_general" indexed="true" stored="true"/>
<field name="original_url" type="string" indexed="true" stored="true"/> <!-- 可选,关联原文档 -->

3.2 配置Nutch到Solr的字段映射

编辑conf/solr-mapping.xml,添加自定义字段的映射:

<field dest="paragraph_position" source="paragraph_position"/>
<field dest="paragraph_section" source="paragraph_section"/>
<field dest="original_url" source="original_url"/>
4. 修正爬取脚本的Solr URL

注意你的原脚本里Solr URL带了/#/,这是UI路径,API请求应该直接指向core,修改为:

bin/crawl -i -D solr.server.url=http://localhost:8983/solr/nutch -s ./urls/ Crawl 2
关键注意事项
  • 测试时先小规模爬取单个站点,查看Solr索引里的段落数据是否正确,包括位置和章节信息。
  • 如果文档中有嵌套的章节结构(比如h2下的h3),可以扩展逻辑调整章节提取规则。
  • 性能方面,长文档拆分后会生成大量索引条目,需根据实际情况调整Solr的索引优化参数。

内容的提问来源于stack exchange,提问作者Alejandro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 11:27:32