WebMagic增量爬取去重 RedisScheduler队列实现

  1. import java.util.HashMap;  
  2. import java.util.Map;  
  3.   
  4. import org.apache.commons.codec.digest.DigestUtils;  
  5. import org.apache.http.NameValuePair;  
  6. import org.apache.http.message.BasicNameValuePair;  
  7.   
  8. import com.alibaba.fastjson.JSON;  
  9. import com.alibaba.fastjson.JSONArray;  
  10. import com.alibaba.fastjson.JSONObject;  
  11.   
  12. import redis.clients.jedis.Jedis;  
  13. import redis.clients.jedis.JedisPool;  
  14. import redis.clients.jedis.JedisPoolConfig;  
  15. import us.codecraft.webmagic.Request;  
  16. import us.codecraft.webmagic.Task;  
  17. import us.codecraft.webmagic.scheduler.component.DuplicateRemover;  
  18.   
  19. /** 
  20.  * Redis中存储着所有抓取到的链接 抓取程序首先判断Redis中是否存在,如果存在该链接直接抛弃. //ERROR 
  21.  *  
  22.  * @author CainGao 
  23.  */  
  24. public class RedisScheduler extends DuplicateRemovedScheduler implements  
  25.         MonitorableScheduler, DuplicateRemover {  
  26.   
  27.     private JedisPool pool;  
  28.   
  29.     private static final String QUEUE_PREFIX = "queue_";  
  30.   
  31.     private static final String SET_PREFIX = "set_";  
  32.   
  33.     private static final String ITEM_PREFIX = "item_";  
  34.   
  35.     public RedisScheduler(String host) {  
  36.         this(new JedisPool(new JedisPoolConfig(), host));  
  37.     }  
  38.   
  39.     public RedisScheduler(JedisPool pool) {  
  40.         this.pool = pool;  
  41.         setDuplicateRemover(this);  
  42.     }  
  43.   
  44.     @Override  
  45.     public void resetDuplicateCheck(Task task) {  
  46.         Jedis jedis = pool.getResource();  
  47.         try {  
  48.             jedis.del(getSetKey(task));  
  49.         } finally {  
  50.             pool.returnResource(jedis);  
  51.         }  
  52.     }  
  53.   
  54.     @Override  
  55.     public boolean isDuplicate(Request request, Task task) {  
  56.         Jedis jedis = pool.getResource();  
  57.         try {  
  58.             boolean isDuplicate = jedis.sismember(getSetKey(task),  
  59.                     request.getUrl());   
  60.             if (!isDuplicate) {  
  61.                 jedis.sadd(getSetKey(task), request.getUrl());   
  62.             }  
  63.             return isDuplicate;  
  64.         } finally {  
  65.             pool.returnResource(jedis);  
  66.         }  
  67.     }  
  68.   
  69.     @Override  
  70.     protected void pushWhenNoDuplicate(Request request, Task task) {  
  71.         Jedis jedis = pool.getResource();  
  72.         try {  
  73.             jedis.rpush(getQueueKey(task), request.getUrl());  
  74.             if (request.getExtras() != null) {  
  75.                 String field = DigestUtils.shaHex(request.getUrl());  
  76.                 String value = JSON.toJSONString(request  
  77.                         .getExtra("nameValuePair"));  
  78.                 jedis.hset((ITEM_PREFIX + task.getUUID()), field, value);  
  79.             }  
  80.         } finally {  
  81.             pool.returnResource(jedis);  
  82.         }  
  83.     }  
  84.   
  85.     /** 
  86.      * 移动并且返回队列头部一个元素 
  87.      */  
  88.     @Override  
  89.     public synchronized Request poll(Task task) {  
  90.         Jedis jedis = pool.getResource();  
  91.         try {  
  92.             String url = jedis.lpop(getQueueKey(task));  
  93.             if (url == null) {  
  94.                 return null;  
  95.             }  
  96.             String key = ITEM_PREFIX + task.getUUID();  
  97.             String field = DigestUtils.shaHex(url);  
  98.             String text = jedis.hget(key, field);  
  99.             if (text != null) {  
  100.                 JSONArray array = JSON.parseArray(text);  
  101.                 NameValuePair[] nameValuePairs = new NameValuePair[array.size()];  
  102.                 for (int i = 0; i < array.size(); i++) {  
  103.                     JSONObject json = JSONObject  
  104.                             .parseObject(array.getString(i));  
  105.                     nameValuePairs[i] = new BasicNameValuePair(  
  106.                             json.getString("name"), json.getString("value"));  
  107.                 }  
  108.                 Request r = new Request(url);  
  109.                 Map<String, Object> map = new HashMap<String, Object>();  
  110.                 map.put("nameValuePair", nameValuePairs);  
  111.                 r.setMethod("post");  
  112.                 r.setExtras(map);  
  113.                 return r;  
  114.             }  
  115.             Request request = new Request(url);  
  116.             return request;  
  117.         } finally {  
  118.             pool.returnResource(jedis);  
  119.         }  
  120.     }  
  121.   
  122.     protected String getSetKey(Task task) {  
  123.         return SET_PREFIX + task.getUUID();  
  124.     }  
  125.   
  126.     protected String getQueueKey(Task task) {  
  127.         return QUEUE_PREFIX + task.getUUID();  
  128.     }  
  129.   
  130.     @Override  
  131.     public int getLeftRequestsCount(Task task) {  
  132.         Jedis jedis = pool.getResource();  
  133.         try {  
  134.             Long size = jedis.llen(getQueueKey(task));  
  135.             return size.intValue();  
  136.         } finally {  
  137.             pool.returnResource(jedis);  
  138.         }  
  139.     }  
  140.   
  141.     @Override  
  142.     public int getTotalRequestsCount(Task task) {  
  143.         Jedis jedis = pool.getResource();  
  144.         try {  
  145.             Long size = jedis.scard(getQueueKey(task));  
  146.             return size.intValue();  
  147.         } finally {  
  148.             pool.returnResource(jedis);  
  149.         }  
  150.     }  
  151.   

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中增量更新和全量更新通常是指数据库中数据的更新。 增量更新是指只更新发生了改变的数据,而不是全部数据。实现方式可以通过在每个数据上添加时间戳或者版本号,当数据发生改变时,只更新时间戳或者版本号发生了改变的数据。 全量更新是指更新全部数据。实现方式可以通过将新数据和旧数据进行比较,然后将旧数据更新为新数据。 在Java中实现增量更新和全量更新可以使用JDBC或者ORM框架(如Hibernate)来操作数据库。下面是一个使用JDBC实现增量更新的示例代码: ```java Connection conn = DriverManager.getConnection(url, username, password); PreparedStatement pstmt = conn.prepareStatement("UPDATE table SET column = ? WHERE id = ?"); pstmt.setString(1, "new value"); pstmt.setInt(2, 1); int rows = pstmt.executeUpdate(); ``` 下面是一个使用JDBC实现全量更新的示例代码: ```java Connection conn = DriverManager.getConnection(url, username, password); PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM table WHERE id = ?"); pstmt.setInt(1, 1); ResultSet rs = pstmt.executeQuery(); if (rs.next()) { // get old data int oldColumnValue = rs.getInt("column"); // get new data int newColumnValue = 2; // update data PreparedStatement updatePstmt = conn.prepareStatement("UPDATE table SET column = ? WHERE id = ?"); updatePstmt.setInt(1, newColumnValue); updatePstmt.setInt(2, 1); int rows = updatePstmt.executeUpdate(); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值