Apache Nutch 2.3.1抓取含波斯-阿拉伯文URL时抛出无效URI异常
这个问题我之前帮不少开发者排查过,核心原因是Nutch 2.3.1依赖的HttpClient 3.x版本不支持直接处理包含非ASCII字符(比如波斯-阿拉伯文)的原始URL——它要求URL必须严格符合RFC标准的ASCII编码格式(也就是我们常说的百分号编码),直接传入带波斯文的URL就会触发你看到的IllegalArgumentException。
下面给你几个可行的解决方案,按实现复杂度从低到高排序:
1. 提前编码种子URL(最快见效)
如果不想改动Nutch代码,最直接的办法就是手动或者用脚本把种子文件里的非ASCII URL转成百分号编码格式。
比如用Python写个简单的处理脚本:
import urllib.parse # 读取原始种子文件,编码后写入新文件 with open('seeds.txt', 'r', encoding='utf-8') as in_file, open('encoded_seeds.txt', 'w', encoding='utf-8') as out_file: for line in in_file: raw_url = line.strip() if not raw_url: continue # 解析URL各部分,只对路径部分编码(避免编码域名等其他部分) parsed_url = urllib.parse.urlparse(raw_url) encoded_path = urllib.parse.quote(parsed_url.path, encoding='utf-8') # 重新拼接成编码后的URL encoded_url = urllib.parse.urlunparse( (parsed_url.scheme, parsed_url.netloc, encoded_path, parsed_url.params, parsed_url.query, parsed_url.fragment) ) out_file.write(f"{encoded_url}\n")
之后用生成的encoded_seeds.txt作为种子文件启动抓取即可。
2. 自定义URL规范化处理器(代码改动小)
Nutch本身支持自定义URL规范化逻辑,我们可以添加一个专门处理非ASCII编码的Normalizer,在URL进入抓取流程前自动完成编码。
步骤如下:
- 新建一个Java类,实现
org.apache.nutch.net.URLNormalizer接口:
import org.apache.commons.codec.net.URLCodec; import org.apache.nutch.net.URLNormalizer; import java.net.MalformedURLException; import java.net.URL; public class NonAsciiUrlNormalizer implements URLNormalizer { private static final URLCodec UTF8_CODEC = new URLCodec("UTF-8"); @Override public String normalize(String url, String scope) throws MalformedURLException { URL originalUrl = new URL(url); // 对URL路径部分进行UTF-8编码 String encodedPath; try { encodedPath = UTF8_CODEC.encode(originalUrl.getPath()); } catch (Exception e) { // 编码失败时返回原始URL,避免中断流程 return url; } // 重新构建编码后的URL URL encodedUrl = new URL( originalUrl.getProtocol(), originalUrl.getHost(), originalUrl.getPort(), encodedPath, originalUrl.getQuery(), originalUrl.getRef() ); return encodedUrl.toString(); } }
- 编译这个类,把打包后的jar放到Nutch的
lib目录下。 - 修改
nutch-site.xml,在urlnormalizer.order配置项中添加自定义Normalizer的全类名,让它在默认Normalizer之前执行:
<property> <name>urlnormalizer.order</name> <value>NonAsciiUrlNormalizer,basic,regex</value> </property>
这样Nutch在处理URL时会自动先对非ASCII路径进行编码,再进入后续流程。
3. 升级HttpClient版本(适合有开发能力的场景)
Nutch 2.3.1依赖的HttpClient 3.x对非ASCII URL的支持确实比较差,如果你愿意花时间调整依赖,可以尝试升级到HttpClient 4.x版本。不过这个方案需要修改Nutch的pom.xml依赖配置,同时适配部分HttpClient相关的代码(因为3.x和4.x的API差异较大),风险相对高一些,适合对Nutch源码有一定了解的开发者。
补充:异常原因说明
你看到的具体异常:
java.lang.IllegalArgumentException: Invalid uri 'http://agahi.safirak.com/ads/850/پیچ-بند-بادی-هفتیری-1800-دور-بادی-جیسون.html': escaped absolute path not valid at org.apache.commons.httpclient.HttpMethodBase.
(HttpMethodBase.java:222)
本质是HttpClient 3.x在构造HttpMethod对象时,会严格校验URL的ASCII编码格式,发现路径中存在非ASCII字符时直接抛出参数非法异常,没有自动编码的逻辑。
内容的提问来源于stack exchange,提问作者Hafiz Muhammad Shafiq

