webmagic
webmagic copied to clipboard
<a href="javascript:"></a>导致的性能问题
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做排除,缺少灵活性。目前想到了就这两种,但感觉都不是一个好的方式。