返回 导航

SpringBoot / Cloud

hangge.com

SpringBoot - 整合webmagic实现爬虫功能教程(附豆瓣数据抓取样例)

作者:hangge | 2024-08-26 09:41

1,基本介绍

(1)webmagic 是一个由国人开发的开源的 Java 垂直爬虫框架,目标是简化爬虫的开发流程,让开发者专注于逻辑功能的开发。webmagic 的核心非常简单,但是覆盖爬虫的整个流程,也是很好的学习爬虫开发的材料。
(2)webmagic 的主要特色:
  • 完全模块化的设计,强大的可扩展性。
  • 核心简单但是涵盖爬虫的全部流程,灵活而强大,也是学习爬虫入门的好材料。
  • 提供丰富的抽取页面 API
  • 无配置,但是可通过“POJO + 注解”形式实现一个爬虫。
  • 支持多线程。
  • 支持分布式。
  • 支持爬取 js 动态渲染的页面。
  • 无框架依赖,可以灵活的嵌入到项目中去。

2,安装配置

Spring Boot 项目的 pom.xml 文件中添加 webmagic 的依赖即可:
(1)webmagic 主要包括两个包:
  • webmagic-corewebmagic 核心部分,只包含爬虫基本模块和基本抽取器。webmagic-core 的目标是成为网页爬虫的一个教科书般的实现。
  • webmagic-extensionwebmagic 的扩展模块,提供一些更方便的编写爬虫的工具。包括注解格式定义爬虫、JSON、分布式等支持。
(2)webmagic 还包含两个可用的扩展包,因为这两个包都依赖了比较重量级的工具,所以从主要包中抽离出来,这些包需要下载源码后自己编译:
  • webmagic-saxonwebmagic Saxon 结合的模块。Saxon 是一个 XPathXSLT 的解析工具,webmagic 依赖 Saxon 来进行 XPath2.0 语法解析支持。
  • webmagic-seleniumwebmagic Selenium 结合的模块。Selenium 是一个模拟浏览器进行页面渲染的工具,webmagic 依赖 Selenium 进行动态页面的抓取。
<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-core</artifactId>
    <version>0.10.0</version>
</dependency>
<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-extension</artifactId>
    <version>0.10.0</version>
</dependency>

3,使用样例

(1)我们要实现一个爬虫能够抓取豆瓣图书里面所有的小说信息,并且运行时能够自动翻页实现连续抓取:

(2)查看页面源码,可以看到相应元素信息如下:

(3)我们在项目中创建一个爬虫类 DoubanBookSpider,具体代码如下:
注意:代码 3031 行我每次只添加分页栏中的后页的链接,其实不必这么麻烦,可以将所有匹配到的分页链接集合都直接调用 page.addTargetRequests() 方法添加进来,即使跳转后的页面分页链接和之前的有重复,webmagic 也会自动剔除,确保不会重复抓取的,或者死循环的。
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
import java.util.Collections;
import java.util.List;

public class DoubanBookSpider implements PageProcessor {

  private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);

  @Override
  public void process(Page page) {
    // 解析页面,提取数据
    List<String> bookNames = page.getHtml().xpath("//*[@id='subject_list']//h2/a/text()").all();
    List<String> bookInfos = page.getHtml()
            .xpath("//*[@id='subject_list']//div[@class='pub']/text()").all();

    // 将数据打印到控制台
    for (int i = 0; i < bookNames.size(); i++) {
      System.out.println("书名:" + bookNames.get(i) + " 信息:" + bookInfos.get(i));
    }

    // 添加下一页的URL,继续爬取
    List<String> links = page.getHtml().links()
            .regex("https://book.douban.com/tag/小说\\?start=\\d+&type=T").all();
    if(links.size() > 0) {
      System.out.println("**************************************");
      // 获取最后一个元素
      String nextPageLink = links.get(links.size() - 1);
      page.addTargetRequests(Collections.singletonList(nextPageLink));
    }
  }

  @Override
  public Site getSite() {
    return site;
  }

  public static void main(String[] args) {
    // 启动爬虫
    Spider.create(new DoubanBookSpider())
            .addUrl("https://book.douban.com/tag/小说")  // 豆瓣图书小说标签页面
            .run();
  }
}

(4)程序运行后爬虫便会自动访问豆瓣图书小说标签页面,并开始抓取数据。

附:使用注解编写爬虫

(1)webmagic-extension 包括了注解方式编写爬虫的方法,只需基于一个 POJO 增加注解即可完成一个爬虫。下面我们使用注解的方式定义一个爬虫:
注解说明:
  • @TargetUrl 是我们最终要抓取的 URL,最终想要的数据都来自这里;
  • @HelpUrl 则是为了发现这个最终 URL,我们需要访问的页面。
  • @ExtractBy 注解主要作用于字段,它表示“使用这个抽取规则,将抽取到的结果保存到这个字段中”
import us.codecraft.webmagic.model.annotation.ExtractBy;
import us.codecraft.webmagic.model.annotation.HelpUrl;
import us.codecraft.webmagic.model.annotation.TargetUrl;
import java.util.List;

// 爬虫页面模型类,用于定义如何抽取目标网页中的数据。
@TargetUrl("https://book.douban.com/tag/小说*")
@HelpUrl("https://book.douban.com/tag/小说\\?start=\\d+&type=T")
public class DoubanBookPageModel {
  public List<String> getBookNames() {
    return bookNames;
  }

  public List<String> getBookInfos() {
    return bookInfos;
  }

  @ExtractBy("//*[@id='subject_list']//h2/a/text()")
  private List<String> bookNames;

  @ExtractBy("//*[@id='subject_list']//div[@class='pub']/text()")
  private List<String> bookInfos;
}

(2)接着我们在程序中使用这个定义的爬虫,并将爬虫抓取的数据打印出来:
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.model.ConsolePageModelPipeline;
import us.codecraft.webmagic.model.OOSpider;

public class DoubanBookSpider2 {
  public static void main(String[] args) {
    // 启动爬虫
    OOSpider.create(Site.me(), new MyPageModelPipeline(), DoubanBookPageModel.class)
            .addUrl("https://book.douban.com/tag/小说").run();
  }
}

// 自定义页面模型管道,继承自ConsolePageModelPipeline
class MyPageModelPipeline extends ConsolePageModelPipeline {
  @Override
  public void process(Object o, Task task) {
    System.out.println("**************************************");
    DoubanBookPageModel douban = (DoubanBookPageModel)o;
    // 将数据打印到控制台
    for (int i = 0; i < douban.getBookNames().size(); i++) {
      System.out.println("书名:" + douban.getBookNames().get(i)
              + " 信息:" + douban.getBookInfos().get(i));
    }
  }
}

(3)程序运行的效果同前面的是一样的:
评论

全部评论(0)

回到顶部