整合 WebMagic

使用 WebMagic 进行网页爬取并入库

本文档提供了使用 Java 和 WebMagic 进行网页爬取的详细指南。内容包括添加依赖项、创建 PageProcessor 进行网页分析、创建 Pipeline 将爬取的数据存入数据库,以及运行测试爬虫。

本示例爬取的网页是 https://www.sis.hawaii.edu/uhdad/avail.classes

1. 添加依赖项

首先,在 pom.xml 文件中添加 WebMagic 所需的依赖项。这些依赖项包括核心的 WebMagic 库及其扩展,并排除 slf4j-log4j12 依赖项以避免冲突。

<dependency>
  <groupId>us.codecraft</groupId>
  <artifactId>webmagic-core</artifactId>
  <version>0.9.1</version>
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>us.codecraft</groupId>
  <artifactId>webmagic-extension</artifactId>
  <version>0.9.1</version>
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
    </exclusion>
  </exclusions>
</dependency>

推荐使用 0.9.1 版本,兼容 jdk 1.8 并且支持 SSL v3

2. 创建 PageProcessor 进行网页分析

接下来,创建一个 PageProcessor 实现来定义网页的处理方式。在本例中,我们从指定的 CSS 选择器中提取链接和名称。

import java.util.List;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;

public class InstitutionProcessor implements PageProcessor {

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

  @Override
  public void process(Page page) {
    String selector = "ul.institutions li a";
    List<String> links = page.getHtml().css(selector, "href").all();
    List<String> names = page.getHtml().css(selector, "text").all();

    page.putField("links", links);
    page.putField("names", names);
  }

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

3. 创建 Pipeline 将数据存入数据库

创建一个 Pipeline 实现来将爬取的数据存入数据库。在本例中,我们使用 Db类 进行数据库操作,并使用 SnowflakeIdGenerator 生成唯一的 ID。

import java.util.List;
import com.litongjava.data.utils.SnowflakeIdGenerator;
import com.litongjava.jfinal.plugin.activerecord.Db;
import com.litongjava.jfinal.plugin.activerecord.Record;
import lombok.extern.slf4j.Slf4j;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;

@Slf4j
public class InstitutionPipeline implements Pipeline {

  @Override
  public void process(ResultItems resultItems, Task task) {
    List<String> links = resultItems.get("links");
    List<String> names = resultItems.get("names");
    // 插入数据库
    for (int i = 0; i < links.size(); i++) {
      String link = links.get(i);
      String[] split = link.split("=");
      if (split.length < 2) {
        continue;
      }
      String abbrName = split[1];
      Integer count = Db.queryInt("select count(1) from institution where abbr_name=?", abbrName);
      if (count > 0) {
        continue;
      } else {
        Record record = new Record();
        record.put("id", new SnowflakeIdGenerator(0, 0).generateId());
        record.put("abbr_name", abbrName);
        record.put("name", names.get(i));
        boolean saved = Db.save("institution", record);
        log.info("Saved {},{}", abbrName, saved);
      }
    }
  }
}

4. 运行爬虫

最后,通过指定要爬取的 URL 并添加 PageProcessorPipeline 实现来运行爬虫。

package com.litongjava.uh.courses.processor;

import org.junit.Test;

import com.litongjava.uh.courses.pipeline.InstitutionPipeline;

import us.codecraft.webmagic.Spider;

public class SpiderInstitutionTest {

  @Test
  public void test() {
    String url = "https://www.sis.hawaii.edu/uhdad/avail.classes";
    Spider.create(new InstitutionProcessor())
        // url
        .addUrl(url) // Add the url you want to scrape
        .addPipeline(new InstitutionPipeline())
        //
        .thread(5).run();
  }

}