本来是想抓取博客园的博客推荐的页面的,但由于一些博客进去的页面格式都不太相同,一时不想花时间去寻找规律,发现CSDN上面的格式较为单一,就决定以CSDN推荐专家的个人博客信息作为爬虫抓取的目标。
【首先,查看一下CSDN的推荐专家的页面】
【然后再查看一下主页面】
准备用爬虫获取一下几个变量
1.姓名
2.访问量
3.积分
4.等级
5.排名
6.原创
7.转载
8.译文
9.评论
10.链接
11.照片
【工程截图】因为主要用到WebMagic,所有的jar包在WebMagic的git地址,自行下载。
【User.java】便于展示,或者后期存入数据库用
package com.cnblogs.test; public class User { private String name; //名字 private String fangwen; //访问数量 private String jifen; //积分 private String dengji; //等级 private String paiming; //排名 private String yuanchuang;//原创 private String zhuanzai; //转载 private String yiwen; //译文 private String pinglun; //评论 private String link; //链接 private String photo; //照片 @Override public String toString() { return " ========================= " + " 姓名=" + name + " 访问量=" + fangwen + " 积分=" + jifen + " 等级=" + dengji + " 排名=" + paiming + " 原创=" + yuanchuang + " 转载=" + zhuanzai + " 译文=" + yiwen + " 评论=" + pinglun + " 链接="+ link + " 照片=" + photo + " ========================== "; }
/*******省略get/Set方法******/ }
【CSDNSpider.java】
package com.cnblogs.test; import java.util.ArrayList; import java.util.HashSet; import java.util.List;import java.util.regex.Matcher; import java.util.regex.Pattern; import us.codecraft.webmagic.Page; import us.codecraft.webmagic.Site; import us.codecraft.webmagic.Spider; import us.codecraft.webmagic.processor.PageProcessor; public class CSDNSpider implements PageProcessor{ private static String keyword="java"; private static int num; //专区网站的相关配置,包括编码、抓取间隔、重试次数等 private Site site=Site.me().setRetryTimes(10).setSleepTime(1000); @Override public Site getSite() { return this.site; } @Override public void process(Page page) { //如果url匹配"http://blog.csdn.net/experts.html" if(page.getUrl().regex("http://blog\.csdn\.net/experts\.html").match()){ //获取div[@class='experts_list_wrap clearfix']内含有的全部链接 List<String> listLink=page.getHtml().xpath("//div[@class='experts_list_wrap clearfix']").links().all(); //因为在首页每个博主都有重复的链接,这里加一个去重的方法,这个方法很好用 HashSet<String> hs=new HashSet<String>(listLink); //通过HashSet剔除重复的链接 listLink.clear(); listLink.addAll(hs); //将去重的的链接结合补充回listStr //将博主的主页的url加入到待抓取的队列中 page.addTargetRequests(listLink); }else{ //此时进入了用户详细页面 User user=new User(); //首先获取姓名 String name=page.getHtml().xpath("//div[@id='blog_userface']/span/a[@class='user_name']/text()").get(); //这里获取 String str=page.getHtml().xpath("//ul[@id='blog_rank']").get()+page.getHtml().xpath("//ul[@id='blog_statistics']").get(); //部分变量以 "<sapn>XXXX<sapm>"的格式存在,我们可以使用正则表达式将整个"<sapn>XXXX<sapm>"获取匹配的字符串 String regex="<span>(.*)+</span>"; Pattern p1=Pattern.compile(regex); Matcher m=p1.matcher(str); //用来保存"<sapn>XXXX<sapm>"中间的XXXX的集合 List<String> strList=new ArrayList<>(); while(m.find()){ //这里的m.group()的格式为: "<span>403581次</span>" 或 "<span>7526</span>" 或 "<span>第1885名</span>" 的格式 String s=m.group().split("<span>|</span>")[1]; //切割之后为 s[0]="<span>" s[1]="404581次" s[2]="<span>",所以我们取s[1] strList.add(s); //将s[1]添加至集合中 } String fangwen=strList.get(0); //访问 String jifen=strList.get(1); //积分 String paiming=strList.get(2); //排名 String yuanchuang=strList.get(3); //原创 String zhuanzai=strList.get(4); //转载 String yiwen=strList.get(5); //译文 String pinglun=strList.get(6); //评论 //等级存放在<img src=http://c.csdnimg.cn/jifen/images/xunzhang/jianzhang/blog6.png>中 //1级对应:blog1.png, 6级对应:blog6.png String dengji=page.getHtml().xpath("//img[@id='leveImg']/@src").get(); dengji=dengji.substring(dengji.length()-5, dengji.length()-4); //获取倒数第5个字符 //获取当前页的url String photo=page.getHtml().xpath("//div[@id='blog_userface']/a/img/@src").get(); String link=page.getUrl().toString(); //将所有的数据保存如User对象中 user.setName(name); user.setFangwen(fangwen); user.setJifen(jifen); user.setDengji(dengji); user.setPaiming(paiming); user.setYuanchuang(yuanchuang); user.setZhuanzai(zhuanzai); user.setYiwen(yiwen); user.setPinglun(pinglun); user.setLink(link); user.setPhoto(photo); System.out.println(user.toString()); } } public static void main(String[] args) { //url入口 Spider.create(new CSDNSpider()) .addUrl("http://blog.csdn.net/experts.html") .thread(5) .run(); } }
【运行结果】
【注意点】
这两块信息分布在两个ul上,所以就出现了程序里
整合两个ul的情况。
另外,注意下这几个处理方式不同
【总结】
知识点一:List<String>去重的方法:
知识点二:正则表达式从一个长字符串中获取符合要求的字符串数组(多个满足条件,就组成数组喽)
知识点三:截取某一段字符串的后面几位(之前有点忘记了,现在记下)
总之WebMagic还是挺好上手的,当然正则表达式巧妙的利用会事半功倍。
另外就是WebMagic的单独的知识点,后面再总结补充。