webmagic是Java语言用于爬虫的工具。官网地址:http://webmagic.io/,中文文档地址:http://webmagic.io/docs/zh/
使用webmagic有3种配置需要注意,日志配置(log4j),webmagic爬取配置(如超时时间),使用数据库的话数据库连接池配置。有一些配置最好做到可以随机器性能情况而改变配置信息。这样做的目的是为了将项目打成包以后在命令行下执行程序可以随时更改配置。因此有些配置文件就不像c3p0配置文件一样放在源码文件夹下,而是相对与项目路径来说。
webmagic的架构图如下:
从该架构图上可以得到一个信息,对于每一个页面来说,都会经历一个完成的过程,即从downloader--->pipeline,如列表页也会进入pipeline,所以列表页虽然没有数据需要存储,但在pipeline中去拿值就会出现空指针,因此在pipeline中要先进行判断,有值的情况下在进行数据库存储操作。
在页面解析部分(待补充),webmagic将解析语法做了一些改变,
1、如将正则表达式中.用.表示
2、*变成了.*,直接使用表示通配符
3、xpath语法也进行了扩充。
代码示例:
webmagic版本:0.6.0
package com.lh.pipeline; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; import us.codecraft.webmagic.ResultItems; import us.codecraft.webmagic.Task; import us.codecraft.webmagic.pipeline.Pipeline; public class MysqlPipeline implements Pipeline { //有一个容器 static DataSource ds = new ComboPooledDataSource();//直接使用即可,不用显示的配置,其会自动识别配置文件 public void process(ResultItems resultItems, Task task) { //每进来一次代表一条记录 //如果容器值达到1000,存一次数据库并将数据清空,否则将数据存入容器 Map<String, Object> m = resultItems.getAll(); if(!m.isEmpty()){ Set<Entry<String, Object>> set = m.entrySet(); Iterator<Entry<String, Object>> reconds = set.iterator(); String url = null; String name = null; String content = null; for(int i=0;i<set.size();i++){ Entry<String, Object> recond =reconds.next(); if(i==0){ url = recond.getValue().toString(); }else if(i==1){ name = recond.getValue().toString(); }else if(i==2){ content = recond.getValue().toString(); } } Connection conn = null; try { conn = ds.getConnection(); String sql = "insert into softList(url,name,content) values(?,?,?)"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, url); pstmt.setString(2, name); pstmt.setString(3, content); pstmt.execute(); pstmt.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
package com.lh.spider; import com.lh.pipeline.MysqlPipeline; import us.codecraft.webmagic.Page; import us.codecraft.webmagic.Site; import us.codecraft.webmagic.Spider; import us.codecraft.webmagic.pipeline.FilePipeline; import us.codecraft.webmagic.processor.PageProcessor; public class ProgramSpider implements PageProcessor { private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(10000); public static final String URL_LIST = "http://www\.xiazaiba\.com/downlist/187_\d{1,4}\.html"; public static final String URL_POST = "http://www\.xiazaiba\.com/html/\d+.html"; public void process(Page page) { if(page.getUrl().regex("http://www\.xiazaiba\.com/downlist/187\.html").match()||page.getUrl().regex(URL_LIST).match()){ //第一页 //加入详情页 //加入列表页 page.addTargetRequests(page.getHtml().xpath("//ul[@class='cur-cat-list']/li/a[1]").links().all()); page.addTargetRequests(page.getHtml().xpath("//div[@class='ylmf-page']").links().all()); }else{ //详情页 page.putField("url", page.getUrl()); page.putField("ProgramName", page.getHtml().xpath("//div[@class='soft-title']/html()")); page.putField("ProgramContent", page.getHtml().xpath("//td[@class='soft-content']/html()")); } } public Site getSite() { return site; } public static void main(String[] args) { Spider.create(new ProgramSpider()) .addUrl("http://www.xiazaiba.com/downlist/187.html") .addPipeline(new MysqlPipeline()).thread(10) .run(); } }