初识webmagic之爬取优快云博客

本文介绍了WebMagic的四大组件:Downloader、PageProcessor、Scheduler、Pipeline,重点讲解了PageProcessor作为核心组件的定制,以及在爬取优快云博客时如何实现抓取特定作者的文章信息,如文章名称、发布日期、阅读量和评论数。

WebMagic的结构分为Downloader、PageProcessor、Scheduler、Pipeline四大组件,并由Spider将它们彼此组织起来。这四大组件对应爬虫生命周期中的下载、处理、管理和持久化等功能。在这四个组件中我们需要做的就是在PageProcessor中写自己的业务逻辑,比如如何解析当前页面,抽取有用信息,以及发现新的链接。

下面是官方给出的架构图

在这里插入图片描述

WebMagic的四个组件
1.Downloader
Downloader负责从互联网上下载页面,以便后续处理。WebMagic默认使用了Apache 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。

用于数据流转的对象

  1. Request
    Request是对URL地址的一层封装,一个Request对应一个URL地址。
    它是PageProcessor与Downloader交互的载体,也是PageProcessor控制Downloader唯一方式。
    除了URL本身外,它还包含一个Key-Value结构的字段extra。你可以在extra中保存一些特殊的属性,然后在其他地方读取,以完成不同的功能。例如附加上一个页面的一些信息等。
  2. Page
    Page代表了从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者其他文本格式的内容。
    Page是WebMagic抽取过程的核心对象,它提供一些方法可供抽取、结果保存等。在第四章的例子中,我们会详细介绍它的使用。
  3. ResultItems
    ResultItems相当于一个Map,它保存PageProcessor处理的结果,供Pipeline使用。它的API与Map很类似,值得注意的是它有一个字段skip,若设置为true,则不应被Pipeline处理。

例子:-----------------------------------

webmagic来爬取优快云上本人博客的文章信息

下面我们通过一个简单的例子来观察webmagic的使用方法以及执行流程。需求:输入作者的用户名,得到该作者文章总数(最简单的办法是直接从首页拿到,我们是爬到一篇文章记录一次),得到所有文章信息(文章名称,发布日期,阅读量,评论数…)

首先加入webmagic依赖,

<dependency>
	<groupId>us.codecraft</groupId>
	<artifactId>webmagic-core</artifactId>
	<version>0.7.3</version>
</dependency>
<dependency>
	<groupId>us.codecraft</groupId>
	<artifactId>webmagic-extension</artifactId>
	<version>0.7.3</version>
</dependency>

然后写一个Processor就搞定了:修改不同的username可以爬取不同的作者。

public class MyPageProcessor implements PageProcessor {

	 private static String username = "Lock_Jun";// 设置csdn用户名
	    private static  int size = 0;// 共抓取到的文章数量
	 
	    // 抓取网站的相关配置,包括:编码、抓取间隔、重试次数等
	    private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
	 
	    public void process(Page page) {
	        if (!page.getUrl().regex("https://blog.youkuaiyun.com/" + username + "/article/details/\\d+").match()) {
	            //获取当前页码
	        	String number=page.getHtml().regex("currentPage\\s*=\\s*(\\d*)",1).toString();
	        	
	            //String number = page.getHtml().xpath("//li[@class='page-item active']//a[@class='page-link']/text()").toString();
	            //匹配当前页码+1的页码也就是下一页,加入爬取列表中
	        	String pageSize =page.getHtml().regex("pageSize\\s*=\\s*(\\d*)",1).toString();//每页文章数
	        	String listTotal  =page.getHtml().regex("listTotal\\s*=\\s*(\\d*)",1).toString();//用户拥有文章数
	        	double maxPage=Math.ceil(Double.parseDouble(listTotal)/Double.parseDouble(pageSize));
	        	if(maxPage>Double.parseDouble(number)) {
	        		//将下一页访问路径放入爬取队列
	        		page.addTargetRequest("http://blog.youkuaiyun.com/"+username+"/article/list/"+(Integer.parseInt(number)+1));
	        	}
	            List<String> detailUrls = page.getHtml().xpath("//h4//a/@href").all();
	            for(String list :detailUrls){
	                System.out.println(list);
	            }
	            page.addTargetRequests(detailUrls);
	        }else {
	            size++;// 文章数量加1
	            String path = page.getUrl().get();
	            int id = Integer.parseInt(path.substring(path.lastIndexOf("/")+1));
	            String title = page.getHtml().xpath("//h1[@class='title-article']/text()").get();
	            String date = page.getHtml().xpath("//div[@class='article-bar-top']//span[@class='time']/text()").get();
	            String copyright = page.getHtml().xpath("//div[@class='article-title-box']//span[@class='article-type type-1 float-left']/text()").get();
	            int view = Integer.parseInt(page.getHtml().xpath("//div[@class='article-bar-top']//span[@class='read-count']/text()").get().substring(4));
	            CsdnBlog csdnBlog = new CsdnBlog(id, date, title, "", view, null, copyright);
	            System.out.println(csdnBlog);
	        }
	    }
	 
	    public Site getSite() {
	        return site;
	    }
	 
	    public static  void main(String[] args) {
	        // 从用户博客首页开始抓,开启5个线程,启动爬虫
	        Spider.create(new MyPageProcessor())
	                .addUrl("https://blog.youkuaiyun.com/" + username)
	                .thread(5).run();
	        System.out.println("文章总数为"+size);
	    }

	
}

自定义的实体类,用来保存爬取的数据,至于之后对数据的保存就随你自己的需求了。

public class CsdnBlog {

	 private Integer id;// 编号
	    private String title;// 标题
	    private String date;// 日期
	    private String category;// 分类
	    private Integer view;// 阅读人数
	    private Integer comments;// 评论人数
	    private String copyright;// 是否原创
	 
	    public CsdnBlog() {}
	    
	    public CsdnBlog(Integer id,String date,String title,String category,Integer view,Integer comments,String copyright){
	        this.id = id;
	    	this.date = date;
	        this.view = view;
	        this.category = category;
	        this.title = title;
	        this.comments = comments;
	        this.copyright = copyright;
	    }

	 
	    @Override
	    public String toString() {
	        return "CsdnBlog{" +
	                "id=" + id +
	                ", title='" + title + '\'' +
	                ", date='" + date + '\'' +
	                ", category='" + category + '\'' +
	                ", view=" + view +
	                ", comments=" + comments +
	                ", copyright='" + copyright + '\'' +
	                '}';
	    }
}

备注:在匹配获取页面信息那个地方(number附近),注意查看网页的document结构是否有变化,对应网页改变即可。

参考链接:https://blog.youkuaiyun.com/yixiao1874/article/details/79496825

### 初识 MyBatis 及其在博客系统中的应用 #### 一、MyBatis 的基本概念 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。消除了几乎所有的 JDBC 代码和参数的手动设置以及结果集的检索。MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plain Old Java Objects)映射成数据库中的记录[^2]。 #### 二、MyBatis 在博客系统的应用场景 在一个典型的博客系统中,MyBatis 主要负责处理数据访问层的任务。通过定义 Mapper 接口来操作数据库表,比如 `BlogMapper` 来管理博客文章的相关 CRUD 操作。对于每一篇博客文章,通常会有对应的实体类 `Blog` 表示一条具体的记录。当用户发布新文章或者编辑已有文章时,这些变更都会被提交至数据库,并由 MyBatis 负责执行相应的 SQL 语句完成更新动作[^1]。 #### 三、MyBatis 的核心组件及其功能 - **SQL 映射文件**:包含了针对特定对象的操作命令,如增删改查等。 - **Mapper Interface**:Java 接口中声明的方法对应于 SQL 映射文件里的 SQL 语句,开发者只需调用相应方法即可实现对数据库的操作而不必关心底层细节[^3]。 - **Result Map (结果映射)**:用来描述数据库返回的结果列如何转换为 Java 对象属性的过程。这使得即使数据库字段名称与 Java 属性不同也能正确匹配。 ```xml <resultMap id="blogResultMap" type="Blog"> <result column="code_id" property="codeId"/> </resultMap> ``` 这段代码展示了如何使用 resultMap 将数据库中的 code_id 字段映射到 Blog 类型的对象属性 codeId 上。 #### 四、缓存机制提升性能 为了优化频繁读取但很少修改的数据查询效率,MyBatis 提供了一套灵活高效的缓存方案。默认情况下启用了名为“一级缓存”的本地缓存特性,它可以减少同一会话期内重复请求相同资源所带来的开销;而更进一步,则可通过配置启用全局性的“二级缓存”,从而在整个应用程序范围内共享已加载过的数据副本,显著降低 I/O 成本并加快响应速度[^4]。 ```java // 开启二级缓存的支持 @CacheNamespace(blocking = true) public interface BlogMapper { } ``` 上述代码片段演示了怎样在 Mapper 中开启二级缓存的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值