替换HTML中的所有URL

3

我正在使用 crawler4j 爬取一些HTML文件,并希望替换这些页面中的所有链接为自定义链接。目前,我可以使用以下代码获取源HTML和所有外链的列表:

        HtmlParseData htmlParseData = (HtmlParseData) page.getParseData();
        String html = htmlParseData.getHtml();
        List<WebURL> links = htmlParseData.getOutgoingUrls();

然而,仅使用简单的foreach循环和搜索替换无法满足我的需求。问题在于WebURL.getURL()将返回绝对URL,但有时链接是相对的,有时不是。
我想处理所有链接(图像、URL、JavaScript文件等)。例如,我想用view.php?url=http://www.domain.com/images/img.gif替换images/img.gif。
唯一的解决方案是使用有点复杂的正则表达式,但我担心会错过一些罕见的情况。这已经做过了吗?是否有库或工具可以实现这一点?

似乎没有这样的工具或库,但是正则表达式是一个强大的工具,迟早你都得学会如何使用它。我建议你立即尝试使用它。你可能还需要为此编写一些单元测试。 - Gavin Xiong
你试过我的答案吗?因为我曾经遇到过和你一样的问题,我使用了这个正则表达式。 - ibrahimyilmaz
@GavinXiong 实际上,我非常熟悉正则表达式。我已经开发了一些工具,可以仅依靠强大的正则表达式修改C++源代码。然而,正如我在下面的评论中提到的那样,可能会出现一些问题,比如格式不正确的HTML。 - Alireza Noori
@AlirezaNoori 我不知道在处理格式错误的HTML时你能做什么...一旦解析器完成了它的工作,那么你所能做的就是处理结果。所以你真的需要修改所有链接吗?可能会有链接到JavaScript、iframe源、嵌入式对象源等。你要在哪里划线呢? - Kiril
@Lirik 不是全部,只有大部分链接。例如,我不想替换电子邮件链接等。至于第一部分,我正在寻找一个解析器,而不是正则表达式。由于crawler4j已经有一个解析器,所以我可能需要修改它的代码。但是,如果提供了更好的解决方案,我宁愿使用它。 - Alireza Noori
显示剩余2条评论
2个回答

0
我认为你可以使用正则表达式来完成这个任务:
例如:
  ...
   String regex = "\\/[^.]*\\/[^.]*\\.";
   Pattern pattern =  Pattern.compile(regex);
   Matcher  matcher = pattern.matcher(text);

   while(matcher.find()){
    String imageLink =  matcher.group();
    text = text.replace(imageLink,prefix+imageLink);
   }

这个正则表达式对于那种用途来说太简单了。它也会替换文本中的URL,我不想要那样。另外,在我的问题中,我提到我有一个正则表达式的想法,但我认为应该有一些编译器来实现更好的结果。例如,可能会有一些格式不正确的HTML无法被正则表达式捕获。 - Alireza Noori
这个正则表达式可以帮助你找到相对URL。一旦你找到了相对URL,你就可以将它们转换成你想要的类型。 - ibrahimyilmaz

0

这一定要用Java解决方案吗?PhantomJspjscrape结合使用可以对网页进行爬取,以查找所有的url。

你只需要创建一个配置的javascript文件即可。

getlinks.js:

pjs.addSuite({
    url: 'https://dev59.com/fGzXa4cB1Zd3GeqPXMGn',
    noConflict: true,
    scraper: function() {
          var links = _pjs.$('a').map(function() {
           // convert relative URLs to absolute
           var link = _pjs.toFullUrl($(this).attr('href'));
           return link;
      });
      return links.toArray();
    }
});
pjs.config({ 
  // options: 'stdout' or 'file' (set in config.outFile)
    log: 'stdout',
    // options: 'json' or 'csv'
    format: 'json',
    // options: 'stdout' or 'file' (set in config.outFile)
    writer: 'stdout',
    scrape_output.json
});

执行命令phantomjs pjscrape.js getlinks.js。在这个例子中,输出结果被存储在一个文件中(也可以记录在控制台中):

以下是(部分)输出结果:

* Suite 0 starting
* Opening https://dev59.com/fGzXa4cB1Zd3GeqPXMGn
* Scraping https://dev59.com/fGzXa4cB1Zd3GeqPXMGn
* Suite 0 complete
* Writing 145 items
["http://stackoverflow.com/users/login?returnurl=%2fquestions%2f14138297%2freplace-all-urls-in-a-html","http://careers.stackoverflow.com","http://chat.stackoverflow.com","http://meta.stackoverflow.com","http://stackoverflow.com/about","http://stackoverflow.com/faq","http://stackoverflow.com/","http://stackoverflow.com/questions","http://stackoverflow.com/tags","http://stackoverflow.com/users","http://stackoverflow.com/badges","http://stackoverflow.com/unanswered","http://stackoverflow.com/questions/ask", ...
"http://creativecommons.org/licenses/by-sa/3.0/","http://creativecommons.org/licenses/by-sa/3.0/","http://blog.stackoverflow.com/2009/06/attribution-required/"]
* Saved 145 items

我的代码是用Java编写的。如果我找不到其他的东西,我可以阅读这段代码并将其移植到Java中。但是,如果可能的话,我希望尽可能少地进行修改 ;) - Alireza Noori

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接