webmagic icon indicating copy to clipboard operation
webmagic copied to clipboard

<a href="javascript:"></a>导致的性能问题

Open GG22G2 opened this issue 3 years ago • 0 comments

page.getHtml().links()使用us.codecraft.webmagic.selector.LinksSelector挑选a标签。

在获取a标签的href属性时,调用会org.jsoup.internal.StringUtil#resolve(java.net.URL, java.lang.String),用来把相对路径的请求转换为绝对路径。resolve中又使用URL类来解析href属性.

对于<a href="javascript:void(0)"></a>,URL类会把href中内容解析为javascript协议,并调用getURLStreamHandler获取协议对应的URLStreamHandler。因为JAVA中没有对javascript协议的实现,会导致大量无用查找过程。

具体影响可能跟javascript:数量有关。 我母亲通过 URL.setURLStreamHandlerFactory来解决,但是setURLStreamHandlerFactory只能被调用一次,感觉很多时候不合适

    URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
        URLStreamHandler javascriptHandler = new URLStreamHandler() {
            @Override
            protected URLConnection openConnection(URL u) throws IOException {
                return null;
            }
        };
        @Override
        public URLStreamHandler createURLStreamHandler(String protocol) {
            switch (protocol) {
                //只需要返回非空就行了
                case "javascript":
                    return javascriptHandler;
            }
            return null;
        }
    });

或者修改us.codecraft.webmagic.selector.LinksSelector#selectList

public List<String> selectList(Element element) {
    Elements elements = element.select("a");
    List<String> links = new ArrayList<>(elements.size());
    for (Element element0 : elements) {
        String href = element0.attr("href").trim();
        String baseUri = element0.baseUri();
        if (baseUri.length()>0 && StringUtils.isNotBlank(baseUri)) {
            if (!href.toLowerCase(Locale.ROOT).startsWith("javascript:")){
                href = StringUtil.resolve(baseUri, href);
            }
            links.add(href);
        }
    }
    return links;
}

URL.setURLStreamHandlerFactory后,程序中其他库或者地方就不能再调用这个方法了。selectList只是对javascript做排除,缺少灵活性。目前想到了就这两种,但感觉都不是一个好的方式。

GG22G2 avatar Jan 10 '22 12:01 GG22G2