本文介绍一下使用webmagic爬虫框架来抓取互联网上的博客文章。
webmagic是一个十分简单的java爬虫框架。
官方文档地址:http://webmagic.io
代码地址:https://github.com/saysky/blog-spider
完整代码可以从上面github里获取,框架采用springboot+jpa+webmagic实现
processor(负责解析页面,并传数据给pipeline)、
pipeline(负责处理数据,如插入数据库)
spider(负责创建爬虫线程,设置队列、pipeline和processor等)
这里主要介绍这三个类的实现。
一、核心代码
1、SegmentfaultPostPageProcessor
package com.liuyanzhao.crawler.component.processor;
import com.liuyanzhao.crawler.entity.Post;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.Selectable;
import java.util.List;
/**
* 文章页面解析
*
* @author 言曌
* @date 2021/6/13 12:58 下午
*/
@Service
public class SegmentfaultPostPageProcessor implements PageProcessor {
@Autowired
private Site site;
/**
* 页面分析
* 使用原生api的jsoup
*
* @param page
*/
public void process(Page page) {
Html html = page.getHtml();
// 解析列表页面的所有链接
List<Selectable> nodes = html.css("h2.blog-type-common").nodes();
if (nodes.size() > 0) {
List<String> links = html.css("h2.blog-type-common").links().all();
System.out.println(links);
page.addTargetRequests(links);
// 解析下一页的URL
List<Selectable> pageNode = html.css("ul.pagination > li.next").nodes();
if (pageNode.size() > 0) {
String nextPageUrl = pageNode.get(0).links().get();
page.addTargetRequest(nextPageUrl);
System.out.println(pageNode);
}
// 不向pipeline传递数据
page.getResultItems().setSkip(true);
}
// 解析详情页面
else {
// 解析文章标题
String title = html.css("div.card-body>h1>a", "text").get();
// 解析文章内容
String content = html.css("article.article-content").get();
// 解析文章作者用户名
String author = html.css("strong.align-self-center", "text").get();
// 页面URL
String url = page.getUrl().get();
Post post = new Post();
post.setTitle(title);
post.setContent(content);
post.setAuthor(author);
post.setSourceUrl(url);
// 把数据传递给pipeline,由pipeline保存到磁盘
page.putField("post", post);
}
}
@Override
public Site getSite() {
return site;
}
}
2、SegmentfaultPostPipeline
package com.liuyanzhao.crawler.component.pipeline;
import cn.hutool.http.HtmlUtil;
import com.liuyanzhao.crawler.dao.PostDao;
import com.liuyanzhao.crawler.entity.Post;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.ListUtils;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;
import java.util.Date;
import java.util.List;
/**
* 采集segmentfault的文章
*
* @author 言曌
* @date 2021/6/13 1:59 下午
*/
@Component
public class SegmentfaultPostPipeline implements Pipeline {
@Autowired
private PostDao postDao;
@Override
@Transactional(rollbackFor = Exception.class)
public void process(ResultItems resultItems, Task task) {
Post post = resultItems.get("post");
// 摘要,截取200个字符
String summaryText = HtmlUtil.cleanHtmlTag(post.getContent());
if (summaryText.length() > 200) {
summaryText = summaryText.substring(0, 200) + "...";
}
post.setSummary(summaryText);
post.setCreateTime(new Date());
post.setSourceSite("segmentfault");
// 把数据存储到数据库
// 判断URL是否已经入库,如果不存在再入库
List<Post> postList = postDao.findBySourceUrl(post.getSourceUrl());
if (ListUtils.isEmpty(postList)) {
postDao.save(post);
}
}
}
3、SegmentfaultPostSpider
package com.liuyanzhao.crawler.component.spider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.pipeline.Pipeline;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.scheduler.Scheduler;
/**
* @author 言曌
* @date 2021/6/13 2:02 下午
*/
@Component
public class SegmentfaultPostSpider {
@Autowired
private PageProcessor pageProcessor;
@Autowired
private Pipeline pipeline;
@Autowired
private Scheduler scheduler;
public static final String START_URL = "https://segmentfault.com/t/java/blogs";
public void doCrawler() {
Spider.create(pageProcessor)
// 设置自定义的pipeline
.addPipeline(pipeline)
// 配置scheduler,指定使用布隆过滤器
.setScheduler(scheduler)
// 设置起始URL
.addUrl(START_URL)
// 启动爬虫
.start();
}
}
二、效果图
结果如下
可能会遇到的问题
请求页面超时,访问页面失败,解决办法待补充
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏