用webmagic写了一个爬虫
爬虫地址:https://job.oschina.net/search?type=%E8%81%8C%E4%BD%8D%E6%90%9C%E7%B4%A2&key=&exp=0&edu=0&nat=1&city=%E5%85%A8%E5%9B%BD&p=1
爬虫所有的招聘职位信息(文末附代码下载及使用说明)
一、查询总的页数
service层代码:
//获取总条数
String spiderUrl = MessageFormat.format(URL, 1);
Spider.create(new TotalPositionPageProcessor()).addUrl(spiderUrl).thread(1).run();
logger.info("总数据量:"+totalPosition+" 总页数:"+totalPage);
创建pageProcess代码:
public class TotalPositionPageProcessor implements PageProcessor{
//抓取网站的相关配置,包括编码、抓取间隔、重试次数等
private Site site = Site.me().setRetryTimes(3).setSleepTime(100);
// process是定制爬虫逻辑的核心接口,在这里编写抽取逻辑
@Override
public void process(Page page) {
// 匹配出总条数
String count = page.getHtml().xpath("//div[@class='layout-column article']/div/div/div[@class='layout-column']/div/text()").regex("([0-9]+)").toString();
logger.info("总数据量为:"+count);
SpiderOschinaServiceImpl.totalPosition = count;
//匹配出总页数
List<String> pageCount = page.getHtml().xpath("//div[@class='pagination text-center']/ul/li/a/text()").all();
logger.info("总页数为:"+pageCount.get(pageCount.size()-2));
SpiderOschinaServiceImpl.totalPage = pageCount.get(pageCount.size()-2);
}
@Override
public Site getSite() {
return site;
}
}
在第一页上有多少个职位多少页数据(https://job.oschina.net/search?type=%E8%81%8C%E4%BD%8D%E6%90%9C%E7%B4%A2&key=&exp=0&edu=0&nat=1&city=%E5%85%A8%E5%9B%BD&p=1)
总页数网页源代码:
通过xpath获取到一共多少职位数据:933
String count = page.getHtml().xpath("//div[@class='layout-column article']/div/div/div[@class='layout-column']/div/text()").regex("([0-9]+)").toString();
通过xpath获取到一共多少页:94
List<String> pageCount = page.getHtml().xpath("//div[@class='pagination text-center']/ul/li/a/text()").all();
logger.info("总页数为:"+pageCount.get(pageCount.size()-2));
SpiderOschinaServiceImpl.totalPage = pageCount.get(pageCount.size()-2);
二、获取每个职位详情
获取每个职位的详情,比如职位、薪资、公司、技能要求
爬取职位详情页:如:https://job.oschina.net/position/11027_2807239_27862
从上面可以获取到一共多少页,所有可以获取到列表页所有的请求地址:
public static List<String> rulList = null;//每一页的请求
if(totalPage!=null && !"".equals(totalPage) && Integer.parseInt(totalPage)>0){
int totalPages = Integer.parseInt(totalPage);
rulList = new ArrayList<String>();
for (int i = 0; i < totalPages; i++) {
System.out.println(MessageFormat.format(URL,i + 1));
rulList.add(MessageFormat.format(URL,i + 1));
}
}
实现pageProcess抓取页面:
//每一个连接都会进入processor方法中进行抽取
public class PositionDetailPageProcessor implements PageProcessor{
//抓取网站的相关配置,包括编码、抓取间隔、重试次数等
private Site site = Site.me().setRetryTimes(3).setSleepTime(100);
//列表页https://job.oschina.net/search?type=%E8%81%8C%E4%BD%8D%E6%90%9C%E7%B4%A2&key=&exp=0&edu=0&nat=1&city=%E5%85%A8%E5%9B%BD&p=1
public static final String URL_LIST = "https://job\\.oschina\\.net/search\\?type=%E8%81%8C%E4%BD%8D%E6%90%9C%E7%B4%A2&key=&exp=0&edu=0&nat=1&city=%E5%85%A8%E5%9B%BD&p=\\d+";
//详情页https://job.oschina.net/position/11317_2828767_27953
public static final String URL_POST = "https://job\\.oschina\\.net/position/\\w+";
//有一个url这个方法和pipeline里的process方法都会再执行一遍
@Override
public void process(Page page) {
//列表页
if(page.getUrl().regex(URL_LIST).match()){
System.out.println("将第几页连接放入待抓取队列中");
page.addTargetRequests(page.getHtml().xpath("//div[@class='layout-left title']/a/@href").all());//获取详情页地址进行结果抽取
page.addTargetRequests(SpiderOschinaServiceImpl.rulList);//获取所有页面的连接并进行抽取
}else{//详情页
System.out.println("抽取详情页数据");
page.putField("name", page.getHtml().xpath("//div[@class='col-xs-9']/h1/@title"));//职位
page.putField("salary", page.getHtml().xpath("//div[@class='col-xs-9']/div/b/text()"));//薪资
String require = page.getHtml().xpath("//span[@id='ex-position-skills']/a/text()").all().toString().replace(",", "/");
page.putField("require", require.substring(1, require.length()-1));//要求
page.putField("company", page.getHtml().xpath("//h3[@class='text-left']/strong/a/text()"));//公司
}
}
@Override
public Site getSite() {
return site;
}
}
page.addTargetRequests方法将链接加入队列中等待下载爬取数据。
每个链接都会实现PageProcessor的process方法和Pipeline的process方法(如果实现了该接口)
三、处理结果
结果处理实现Pipeline接口
public class PositionDetailPipeline implements Pipeline{
@Override
public void process(ResultItems resultItems, Task task) {
System.out.println("输出结果:");
//遍历所有结果,输出到控制台,上面例子中的"name"、"require"、"salary"、"company"都是一个key,其结果则是对应的value
for (Map.Entry<String, Object> entry : resultItems.getAll().entrySet()) {
System.out.println(entry.getKey() + " --------------------> " + entry.getValue());
}
}
}
打印处理的结果:
输出结果:
name --------------------> 前端开发工程师 (Web方向) (接受实习生和兼职顾问)
salary --------------------> 4K-8K
require --------------------> html5/ mysql/ php/ html+css+jq/ PS
company --------------------> 嘉兴想天信息科技有限公司
四、代码下载
代码下载地址:http://download.youkuaiyun.com/detail/u012385190/9696972
本项目使用maven环境搭建,运行是用quartz定时器启动项目的。如果不熟悉quartz,也可以直接在类SpiderOschinaServiceImpl运行main方法即可。