当前位置: 首页 > 工具软件 > Web-Harvest > 使用案例 >

Web-Harvest学习笔记

郎欣然
2023-12-01
文章来源[url]http://mxsfengg.blog.163.com/blog/static/2637021820085522154653/[/url]
这一章,我们来学习scraper的源码。

首先,我们来看下scrape的构造函数,

public Scraper(ScraperConfiguration configuration, String workingDir) {
this.configuration = configuration;
this.runtimeConfig = new RuntimeConfig();
this.workingDir = CommonUtil.adaptFilename(workingDir);

this.httpClientManager = new HttpClientManager();

this.context = new ScraperContext(this);
this.scriptEngine = configuration.createScriptEngine(this.context);
this.usedScriptEngines.put(configuration.getDefaultScriptEngine(), this.scriptEngine);
}

传入的参数有两个,一个scraper的配置类,一个工作目录。其中下面是实例化ScraperConfiguration 的代码

ScraperConfiguration config = new ScraperConfiguration("G:/web_harvest/crawlerSinger.xml");

其实就是向系统加载这个xml配置文件,这个配置文件中包括了抓取的流程,以及一些细节。

当然,这个构造函数,还做了一些其他的事情:

1 初始化了runtimeConfig

2 初始化了workingDir

3 初始化了httpClientManager

4 初始化了context

5 初始化了scriptEngine

6 将scriptEngine 放进usedScriptEngines

上面出现了许多没有新类,为了下一步更好的对这个源码的理解,我觉得有必要对这些类进行一些探讨。

一、ScraperConfiguration ,以下是ScraperConfiguration 的部分源码,

public class ScraperConfiguration {

//以下是四个常量的声明,从这里我们也可以看出web-harvest支持的动态语言有三种包括beanshell, javascript
//和groovy。默认的编码是utf-8

public static final String BEANSHELL_SCRIPT_ENGINE = "beanshell";
public static final String JAVASCRIPT_SCRIPT_ENGINE = "javascript";
public static final String GROOVY_SCRIPT_ENGINE = "groovy";

public static final String DEFAULT_CHARSET = "UTF-8";

// map of function definitions
private Map functionDefs = new Catalog();//其实就是一个hashmap

// sequence of operationDefs
private List operations = new ArrayList();

private String charset = DEFAULT_CHARSET;

//可以看到默认情况下是支持beanshell的
private String defaultScriptEngine = BEANSHELL_SCRIPT_ENGINE;

private File sourceFile;
private String url;

/**
*构造函数,从流中构造配置

*/
public ScraperConfiguration(InputSource in) {
createFromInputStream(in);

}

/* 一个比较重要的方法,供构造函数调用,构造函数的主要的工作就是它做的*/

private void createFromInputStream(InputSource in) {
// loads configuration from input stream to the internal structure
XmlNode node = XmlNode.getInstance(in);//xmlNode 是一个对xml的封装类,在此我们并不打算对它进行深
//究,只需记得它封装了对xml的操作。

//设置charset,默认情况下是utf-8

String charsetString = node.getString("charset");
this.charset = charsetString != null ? charsetString : DEFAULT_CHARSET;

//设置动态语言引擎类型,默认情况下支持beanshell

String scriptEngineDesc = node.getString("scriptlang");
if ( "javascript".equalsIgnoreCase(scriptEngineDesc) ) {
this.defaultScriptEngine = JAVASCRIPT_SCRIPT_ENGINE;
} else if ( "groovy".equalsIgnoreCase(scriptEngineDesc) ) {
this.defaultScriptEngine = GROOVY_SCRIPT_ENGINE;
} else {
this.defaultScriptEngine = BEANSHELL_SCRIPT_ENGINE;
}

//遍历根元素的所有的子节点,将这些子结点放进operations中。这样初始化工作就基本ok了,下面就是对operations中的这些xml节点进行解析、执行。具体的细节后面我们分析

List elementList = node.getElementList();
Iterator it = elementList.iterator();
while (it.hasNext()) {
Object element = it.next();
if (element instanceof XmlNode) {
XmlNode currElementNode = (XmlNode) element;
operations.add( DefinitionResolver.createElementDefinition(currElementNode) );
} else {
operations.add( new ConstantDef(element.toString()) );
}
}
}

//构造函数,具体的实现同上

public ScraperConfiguration(File sourceFile) throws FileNotFoundException {
this.sourceFile = sourceFile;
createFromInputStream( new InputSource(new FileReader(sourceFile)) );
}

//构造函数,具体的实现同上
public ScraperConfiguration(String sourceFilePath) throws FileNotFoundException {
this( new File(sourceFilePath) );
}

//构造函数,具体的实现同上

public ScraperConfiguration(URL sourceUrl) throws IOException {
this.url = sourceUrl.toString();
createFromInputStream( new InputSource(new InputStreamReader(sourceUrl.openStream())) );
}

//创建动态语言引擎

public ScriptEngine createScriptEngine(Map context, String engineType) {
if ( JAVASCRIPT_SCRIPT_ENGINE.equalsIgnoreCase(engineType) ) {
return new JavascriptScriptEngine(context);
} else if ( GROOVY_SCRIPT_ENGINE.equalsIgnoreCase(engineType) ) {
return new GroovyScriptEngine(context);
} else {
return new BeanShellScriptEngine(context);
}
}

public ScriptEngine createScriptEngine(Map context) {
return createScriptEngine(context, this.defaultScriptEngine);
}

}

由于篇幅原因,我们在下面几张分别讨论httpClientManager ,runtimeConfig ,context
 类似资料: