设为首页 收藏本站
查看: 1067|回复: 0

[经验分享] webmagic自定义存储(mysql、redis存储)

[复制链接]

尚未签到

发表于 2017-12-21 23:57:44 | 显示全部楼层 |阅读模式
  在很多时候,我们使用webmagic爬取网站的时候,爬取的数据希望存储在mysql、redis中。因此需要对其扩展,实行自定义PipeLine。首先我们了解一下webmagic 的四个基本组件

一、 WebMagic的四个组件

1、Downloader
  Downloader负责从互联网上下载页面,以便后续处理。WebMagic默认使用了HttpClient作为下载工具。

2、PageProcessor
  PageProcessor负责解析页面,抽取有用信息,以及发现新的链接。WebMagic使用Jsoup作为HTML解析工具,并基于其开发了解析XPath的工具Xsoup。
  在这四个组件中,PageProcessor对于每个站点每个页面都不一样,是需要使用者定制的部分。

3、Scheduler
  Scheduler负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重。也支持使用Redis进行分布式管理。
  除非项目有一些特殊的分布式需求,否则无需自己定制Scheduler。

4、Pipeline
  Pipeline负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。
  Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。对于一类需求一般只需编写一个Pipeline。

二、自定义Pipeline,实现Pipeline接口,从写process方法。
  

package com.mdd.pip.pipeLine;  

  

import java.util.List;  

  

import org.springframework.beans.factory.annotation.Autowired;  

import org.springframework.stereotype.Component;  

import com.mdd.pip.model.ProxyIp;  

import com.mdd.pip.service.ProxyIpService;  

  

import us.codecraft.webmagic.ResultItems;  

import us.codecraft.webmagic.Task;  

import us.codecraft.webmagic.pipeline.Pipeline;  

  
@Component
  

public>
  @Autowired
private ProxyIpService proxyIpService;  

/**  * mysql 存储
*/  /*
  * public void process(ResultItems resultItems, Task task) {
  * List<ProxyIp>proxyIpList = resultItems.get("proxyIpList");
  * if(proxyIpList!=null&&!proxyIpList.isEmpty()){
  * proxyIpService.saveProxyIpList(proxyIpList); }
  *
  * }
  */
  

  /**
  * redis 存储
  */
  public void process(ResultItems resultItems, Task task) {
  List<ProxyIp> proxyIpList = resultItems.get("proxyIpList");
  if (proxyIpList != null && !proxyIpList.isEmpty()) {
  proxyIpService.saveProxyListIpInRedis(proxyIpList);
  }
  

  }
  
}
  

  

ResultItems 对象本质是一个Map。因此要我们保存对象的时候,只需要在爬取时把爬取得数据封装成对象,保存在  

ResultItems 里即可。如果有很多数据,则可以考虑用List保存。  

  

package com.mdd.pip.crawler;  

  

import java.util.ArrayList;  

import java.util.List;  

  

import org.apache.log4j.Logger;  

import org.jsoup.nodes.Document;  

import org.jsoup.nodes.Element;  

import org.jsoup.select.Elements;  

import org.springframework.stereotype.Component;  

  

import com.mdd.pip.model.ProxyIp;  

import us.codecraft.webmagic.Page;  

import us.codecraft.webmagic.Site;  

import us.codecraft.webmagic.processor.PageProcessor;  

  

/**  * 热刺代理网站ip抓取
  *
  *
@author xwl 2017.6.3*/  
@Component
  

public>
private Logger logger = Logger.getLogger(XiCiProxyIpCrawler.class);  

// 部分一:抓取网站的相关配置,包括编码、抓取间隔、重试次数等  private Site site = Site.me().setCycleRetryTimes(3).setRetryTimes(3).setSleepTime(1000)
  .setUserAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0");
  

  public Site getSite() {
  return site;
  }
  

  public void process(Page page) {
  Document html = page.getHtml().getDocument();
  // 结果集
  List<ProxyIp> proxyIpList = new ArrayList<ProxyIp>();
  Elements trElements = html.getElementById("ip_list").getElementsByTag("tr");
  for (Element trEle : trElements) {
  Elements tdElements = trEle.getElementsByTag("td");
  if (tdElements == null||tdElements.size()<=0) {
  continue;
  }
  try {
  ProxyIp proxyIp = new ProxyIp();
  String ip = tdElements.get(1).text();
  String proxyPort = tdElements.get(2).text();
  String ipAddress = tdElements.get(3).text();
  String anonymity = tdElements.get(4).text();
  String proxyType = tdElements.get(5).text();
  String aliveTime = tdElements.get(6).text();
  proxyIp.setProxyIp(ip);
  proxyIp.setProxyPort(Integer.parseInt(proxyPort));
  proxyIp.setAliveTime(aliveTime);
  proxyIp.setAnonymity(anonymity);
  proxyIp.setIpAddress(ipAddress);
  proxyIp.setProxyType(proxyType);
  logger.info(proxyIp.getProxyIp()+":"+proxyIp.getProxyPort());
  proxyIpList.add(proxyIp);
  } catch (Exception e) {
  logger.error("IP代理解析出错!", e);
  }
  }
  page.putField("proxyIpList", proxyIpList);
  }
  
}
  

  

page.putField("proxyIpList", proxyIpList);本质是设值到了ResultItems对象里了。  这样插件式、定制化很值的我们借鉴。希望下一步看源码。
  参考:
  http://webmagic.io/docs/zh/posts/ch1-overview/architecture.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-426679-1-1.html 上篇帖子: redis: 6379端口下set值时出现 CLUSTERDOWN The cluster is down 下篇帖子: .NET中使用Redis总结(一)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表