需要使用爬虫这个东西,所以我研究了一下子这个东西。
WebHarvest是个挺强大的爬虫,主要不是在Java代码那块使用,而是需要写脚本。
现在对WebHarvest这个配置的语法也不是很熟,只是写写使用经验。
外话:虽然我很烦写脚本,不过用着用着,我也觉得脚本的好处,发现脚本粘合性用在项目中也是很不错的。
可以到www.webharvest.org网上下载jar包。
其中还有一个方便调试的脚步本的工具:
下载这个文件,可以双击,也可以使用java -jar 命令打开。
软件如下:
也可以使用代码执行脚本:
- //输入配置文件名
- String scriptFile = "c:/mumu/tmp/webharvest/test2.xml";
- //输入内容的存放文件夹路径
- String outDirectory = "c:/mumu/tmp/webharvest";
- ScraperConfiguration config = new ScraperConfiguration(scriptFile);
- Scraper scraper = new Scraper(config, outDirectory);
- scraper.setDebug(true);
- long startTime = System.currentTimeMillis();
- scraper.execute();
- System.out.println("time elapsed: " + (System.currentTimeMillis() - startTime));
//输入配置文件名
String scriptFile = "c:/mumu/tmp/webharvest/test2.xml";
//输入内容的存放文件夹路径
String outDirectory = "c:/mumu/tmp/webharvest";
ScraperConfiguration config = new ScraperConfiguration(scriptFile);
Scraper scraper = new Scraper(config, outDirectory);
scraper.setDebug(true);
long startTime = System.currentTimeMillis();
scraper.execute();
System.out.println("time elapsed: " + (System.currentTimeMillis() - startTime));
现在开始编写配置文件:
- <?xml version="1.0" encoding="utf-8"?>
- <config charset="utf-8">
- <var-def name="start">
- <html-to-xml>
- <http url="http://www.tianya.cn/bbs/index.shtml" charset="utf-8" />
- </html-to-xml>
- </var-def>
- <var-def name="ulList">
- <xpath expression="//div[@class='bankuai_list']">
- <var name="start" />
- </xpath>
- </var-def>
- <file action="write" path="tianya/siteboards.xml" charset="utf-8">
- <![CDATA[ <site> ]]>
- <loop item="item" index="i">
- <list><var name="ulList"/></list>
- <body>
- <xquery>
- <xq-param name="item">
- <var name="item"/>
- </xq-param>
- <xq-expression><![CDATA[
- declare variable $item as node() external;
- <board boardname="{normalize-space(data($item//h3/text()))}" boardurl="">
- {
- for $row in $item//li return
- <board boardname="{normalize-space(data($row//a/text()))}" boardurl="{normalize-space(data($row/a/@href))}" />
- }
- </board>
- ]]></xq-expression>
- </xquery>
- </body>
- </loop>
- <![CDATA[ </site> ]]>
- </file>
- </config>
<?xml version="1.0" encoding="utf-8"?>
<config charset="utf-8">
<var-def name="start">
<html-to-xml>
<http url="http://www.tianya.cn/bbs/index.shtml" charset="utf-8" />
</html-to-xml>
</var-def>
<var-def name="ulList">
<xpath expression="//div[@class='bankuai_list']">
<var name="start" />
</xpath>
</var-def>
<file action="write" path="tianya/siteboards.xml" charset="utf-8">
<![CDATA[ <site> ]]>
<loop item="item" index="i">
<list><var name="ulList"/></list>
<body>
<xquery>
<xq-param name="item">
<var name="item"/>
</xq-param>
<xq-expression><![CDATA[
declare variable $item as node() external;
<board boardname="{normalize-space(data($item//h3/text()))}" boardurl="">
{
for $row in $item//li return
<board boardname="{normalize-space(data($row//a/text()))}" boardurl="{normalize-space(data($row/a/@href))}" />
}
</board>
]]></xq-expression>
</xquery>
</body>
</loop>
<![CDATA[ </site> ]]>
</file>
</config>
输出结果我就不打印出来了,这个脚本例子是网上的。
先简单地说一个这个配置文件的写法
<var-def name="a">abc</var-def>
这里定义了一个a 变量标签的内容就是a的值。
现在a的值就是abc。
然而如果我现在需要爬baidu的页面,就需要先将http://www.baidu.com这个页面给下载下来先。
可以使用标签
<http url="www.baidu.com" charset="utf-8" />
这个标签将代码返回下载下来所有的页面代码,此时需要有一个变量去存起来,可以使用
- <var-def name="baiduall">
- <http url="www.baidu.com" charset="utf-8" />
- </var-def>
<var-def name="baiduall">
<http url="www.baidu.com" charset="utf-8" />
</var-def>
需要抓内容的必须将html转成xml,这样可以方便以DOM 的方式去定位信息内容。
现在可以使<html to xml标签.
- <var-def name="baiduall">
- <http url="www.baidu.com" charset="utf-8" />
- </var-def>
- <var-def name="baiduxml">
- <html-to-xml>
- <var name="baiduall" />
- </html-to-xml>
- </var-def>
<var-def name="baiduall">
<http url="www.baidu.com" charset="utf-8" />
</var-def>
<var-def name="baiduxml">
<html-to-xml>
<var name="baiduall" />
</html-to-xml>
</var-def>
上边的代码先使用<var标签去引用这baiduall变量。再使用<html-to-xml>标签处理
然后用baiduxml变量存放转成xml后的内容。
这里只是为了演示这个功能,其实可以简化成如下代码:
- <var-def name="baiduxml">
- <html-to-xml>
- <http url="www.baidu.com" charset="utf-8" />
- </html-to-xml>
- </var-def>
<var-def name="baiduxml">
<html-to-xml>
<http url="www.baidu.com" charset="utf-8" />
</html-to-xml>
</var-def>
这代码与上边代码意义相同。
先在这里介绍最简单的用法,时间关系,我会日后与大家分享更多的功能方式讨论。
以后再讨论:
包括使用XPath定位与用js处理代码,<file标签输出到文件中,或是将数据在转到java对象中。
除了使用上述方法外,还可以使用将不页的数据输出到不同的结构化好的XML文件里面,
然后再进行读取的方法:
配置文件:
- <var-def name="targetUrl">http://www.51zyr.com/tpl/index/hotel_list_web.do</var-def>
- <var name="page_num"/>
- <file action="write" path="hotel_page${page_num}.xml">
- <template>
- <![CDATA[ <root> ]]>
- </template>
- <loop item="item" index="i">
- <list>
- <xpath expression="//table[@background='../images/dotline.gif'][1]/tbody/tr">
- <html-to-xml>
- <http url="${targetUrl}?pages=${page_num}"/> //这里根据从JAVA文件传过来的参数进行不同页面的查询抓取
- </html-to-xml>
- </xpath>
- </list>
- <body>
- <xquery>
- <xq-param name="item">
- <var name="item"/>
- </xq-param>
- <xq-expression><![CDATA[
- declare variable $item as node() external;
- let $num := data($item//td[1])
- let $name := data($item//td[2])
- let $star := data($item//td[3])
- let $address := data($item//td[4])
- let $telephone := data($item//td[5])
- return
- <hotel>
- <num>{data($num)}</num>
- <name>{data($name)}</name>
- <star>{data($star)}</star>
- <address>{data($address)}</address>
- <telephone>{data($telephone)}</telephone>
- </hotel>
- ]]></xq-expression>
- </xquery>
- </body>
- </loop>
- <![CDATA[ </root> ]]>
- </file>
接着是JAVA文件里面的关键代码:
- public void QueryPath(int num)
- {
- try{
- ScraperConfiguration config = new ScraperConfiguration("traveldata/config/hotel.xml");
- Scraper scraper = new Scraper(config, "traveldata/output/hotel");
- scraper.addVariableToContext("page_num", new String(""+num));
- scraper.setDebug(true);
- long starttime = System.currentTimeMillis();
- scraper.execute();
- long endtime = System.currentTimeMillis();
- System.out.println("Spent time:"+(endtime - starttime));
- saveHotel(num);
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
- public void getContent(int pageNum) //循环调用
- {
- for(int i=1;i<=pageNum;i++)
- {
- QueryPath(i);
- }
- }