十次方人工智能筆記一:網絡爬蟲

爬蟲框架WebMagic

架構解析

WebMagic的設計目標是儘量的模塊化,並體現爬蟲的功能特點。這部分提供非常簡單、靈活的API,在基本不改變開發模式的情況下,編寫一個爬蟲。

WebMagic的結構分爲DownloaderPageProcessorSchedulerPipeline四大組件,並由Spider將它們彼此組織起來。這四大組件對應爬蟲生命週期中的下載、處理、管理和持久化等功能。而Spider則將這幾個組件組織起來,讓它們可以互相交互,流程化的執行,可以認爲Spider是一個大的容器,它也是WebMagic邏輯的核心。

WenMagic組件:

  • Downloader

    Downloader負責從互聯網上下載頁面,以便後續處理。WebMagic默認使用了ApacheHttpClient作爲下載工具。

  • PageProcesser

    PageProcessor負責解析頁面,抽取有用信息,以及發現新的鏈接。WebMagic使用Jsoup作爲HTML解析工具,並基於其開發瞭解析XPath的工具Xsoup

    在這四個組件中,PageProcessor對於每個站點每個頁面都不一樣,是需要使用者定製的部分。

  • Scheduler

    Scheduler負責管理待抓取的URL,以及一些去重的工作。WebMagic默認提供了JDK的內存隊列來管理URL,並用集合來進行去重。也支持使用Redis進行分佈式管理。

  • Pipeline

    Pipeline負責抽取結果的處理,包括計算、持久化到文件、數據庫等。WebMagic默認提供了“輸出到控制檯”和“保存到文件”兩種結果處理方案。

API

Spider API

方法 說明 示例
create(PageProcessor) 創建Spider Spider.create(new GithubRepoProcessor())
addUrl(String…) 添加初始的URL Spider.addUrl(“http://webmagic.io/docs/”)
thread(n) 開啓n個線程 Spider.thread(5)
run() 啓動,會阻塞當前線程執行 Spider.run()
start()/runAsync() 異步啓動,當前線程繼續執行 Spider.start()
stop() 停止爬蟲 Spider.stop()
addPipeline(Pipeline) 添加一個Pipeline,一個Spider可以有多個Pipeline Spider .addPipeline(new ConsolePipeline())
setScheduler(Scheduler) 設置Scheduler,一個Spider只能有一個Scheduler Spider.setScheduler(new RedisScheduler())
setDownloader(Downloader) 設置Downloader,一個Spider只能有一個Downloader Spider.setDownloader(new SeleniumDownloader())
get(String) 同步調用,並直接取得結果 ResultItems result = Spider.get(“http://webmagic.io/docs/”)
getAll(String…) 同步調用,並直接取得一堆結果 List results = Spider.getAll(“http://webmagic.io/docs/”,“http://webmagic.io/xxx”)

同時Spider的其他組件(Downloader、Scheduler、Pipeline)都可以通過set方法來進行設置。

Site API

方法 說明 示例
setCharset(String) 設置編碼 site.setCharset(“utf-8”)
setUserAgent(String) 設置UserAgent site.setUserAgent(“Spider”)
setTimeOut(int) 設置超時時間, 單位是毫秒 site.setTimeOut(3000)
setRetryTimes(int) 設置重試次數 site.setRetryTimes(3)
setCycleRetryTimes(int) 設置循環重試次數 site.setCycleRetryTimes(3)
addCookie(String,String) 添加一條cookie site.addCookie(“dotcomt_user”,“code4craft”)
setDomain(String) 設置域名,需設置域名後,addCookie纔可生效 site.setDomain(“github.com”)
addHeader(String,String) 添加一條addHeader site.addHeader(“Referer”,“https://github.com”)
setHttpProxy(HttpHost) 設置Http代理 site.setHttpProxy(new HttpHost(“127.0.0.1”,8080))
setSleepTime 間隔時間設置 site.setSleepTime(100)

PageProcessor

爬取頁面全部內容

需求:編寫爬蟲程序,爬取csdn中博客的內容 https://blog.csdn.net/

  1. 創建工程,引入依賴

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.xushuai</groupId>
        <artifactId>webmagic_demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    
    
        <dependencies>
            <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>
        </dependencies>
    </project>
    
  2. 實現頁面爬取

    package com.xushuai.magic.spider;
    
    import us.codecraft.webmagic.Page;
    import us.codecraft.webmagic.Site;
    import us.codecraft.webmagic.Spider;
    import us.codecraft.webmagic.pipeline.ConsolePipeline;
    import us.codecraft.webmagic.processor.PageProcessor;
    
    /**
     * Spider Class Demo
     */
    public class PageProcessorDemo1 implements PageProcessor {
    
    
        public void process(Page page) {
            System.out.println(page.getHtml().toString());
        }
    
        public Site getSite() {
            return Site.me().setSleepTime(100).setRetryTimes(3);
        }
    
        public static void main(String[] args) {
            Spider.create(new PageProcessorDemo1())
                    // 添加爬取的主網站
                    .addUrl("https://www.csdn.net/")
                    .run();
        }
    }
    

    Page代表了從Downloader下載到的一個頁面——可能是HTML,也可能是JSON或者 其他文本格式的內容。Page是WebMagic抽取過程的核心對象,它提供一些方法可供抽取、結果保存等。

    Site用於定義站點本身的一些配置信息,例如編碼、HTTP頭、超時時間、重試策略等、代理等,都可以通過設置Site對象來進行配置。

爬取指定內容

使用xpath來抓去網頁指定部分內容

page.getHtml().xpath("//*[@id=\"nav\"]/div/div/ul/li[5]/a");

添加目標地址

添加目標地址,將目標地址中所有的鏈接添加到待爬取列表

page.addTargetRequests(page.getHtml().links().all());

目標地址正則匹配

需求:只提取博客的文章詳細頁內容,並提取標題

page.addTargetRequests(page.getHtml()
                .links().regex("https://blog.csdn.net/[a-z 0-9-]+/article/details/[0-9]{8}").all());

Pipeline

ConsolePipeline 控制檯輸出(省略)

FilePipeline 文件輸出

    public static void main(String[] args) {
        Spider.create(new PageProcessorDemo1())
                // 添加爬取的主網站
                .addUrl("https://www.csdn.net/")
                // 添加控制檯輸出管道
                .addPipeline(new ConsolePipeline())
                // 添加文件輸出管道
                .addPipeline(new FilePipeline("F:/data"))
                .run();
    }

JsonFilePipeline Json輸出

    public static void main(String[] args) {
        Spider.create(new PageProcessorDemo1())
                // 添加爬取的主網站
                .addUrl("https://www.csdn.net/")
                // 添加控制檯輸出管道
                .addPipeline(new ConsolePipeline())
                // 添加文件輸出管道
                .addPipeline(new FilePipeline("F:/data"))
                // 添加Json輸出管道
                .addPipeline(new JsonFilePipeline("F:/json"))
                .run();
    }

Custom Pipeline 自定義輸出

  • 編寫自定義管道類

    package com.xushuai.magic.pipeline;
    
    import us.codecraft.webmagic.ResultItems;
    import us.codecraft.webmagic.Task;
    import us.codecraft.webmagic.pipeline.Pipeline;
    
    /**
     * 自定義輸出管道
     */
    public class CustomPipeline implements Pipeline {
        public void process(ResultItems resultItems, Task task) {
            System.out.println(resultItems.get("title"));
        }
    }
    
  • 添加自定義管道

        public static void main(String[] args) {
            Spider.create(new PageProcessorDemo1())
                    // 添加爬取的主網站
                    .addUrl("https://www.csdn.net/")
                    // 添加控制檯輸出管道
                    .addPipeline(new ConsolePipeline())
                    // 添加文件輸出管道
                    .addPipeline(new FilePipeline("F:/data"))
                    // 添加Json輸出管道
                    .addPipeline(new JsonFilePipeline("F:/json"))
                    // 添加自定義管道
                    .addPipeline(new CustomPipeline())
                    .run();
        }
    

Scheduler

Scheduler(URL管理) 最基本的功能是實現對已經爬取的URL進行標示。可以實現URL的增量去重。

目前Scheduler主要有三種實現方式:

  • 內存隊列:QueueScheduler
  • 文件隊列:FileCacheQueueScheduler
  • Redis隊列:RedisScheduler

內存隊列

    public static void main(String[] args) {
        Spider.create(new PageProcessorDemo1())
                // 添加爬取的主網站
                .addUrl("https://www.csdn.net/")
                // 添加內存隊列
                .setScheduler(new QueueScheduler())
                .run();
    }

文件隊列

使用文件保存抓取URL,可以在關閉程序並下次啓動時,從之前抓取到的URL繼續抓取。

    public static void main(String[] args) {
        Spider.create(new PageProcessorDemo1())
                // 添加爬取的主網站
                .addUrl("https://www.csdn.net/")
                // 添加文件隊列
                .setScheduler(new FileCacheQueueScheduler("F:/scheduler"))
                .run();
    }

Redis隊列

使用Redis保存抓取隊列,可進行多臺機器同時合作抓取。

    public static void main(String[] args) {
        Spider.create(new PageProcessorDemo1())
                // 添加爬取的主網站
                .addUrl("https://www.csdn.net/")
                // 添加Redis隊列
                .setScheduler(new RedisScheduler("192.168.136.104"))
                .run();
    }

十次方文章數據爬取

需求:每日某時間段從CSDN播客中爬取文檔,存入文章數據庫中。

準備工作

  1. CSDN中各個頻道的地址

    頻道名稱 地址
    資訊 https://blog.csdn.net/nav/news
    人工智能 https://blog.csdn.net/nav/ai
    區塊鏈 https://blog.csdn.net/nav/blockchain
    數據庫 https://blog.csdn.net/nav/db
    前端 https://blog.csdn.net/nav/web
    編程語言 https://blog.csdn.net/nav/lang
  2. 向數據庫tensquare_article中的tb_channel表中添加記錄

文章爬取微服務

創建Module

  1. pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>tensquare_parent</artifactId>
            <groupId>com.tensquare</groupId>
            <version>1.0.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>tensquare_article_crawler</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>us.codecraft</groupId>
                <artifactId>webmagic-core</artifactId>
                <version>0.7.3</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.7.3</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>com.tensquare</groupId>
                <artifactId>tensquare_common</artifactId>
                <version>${tensquare.version}</version>
            </dependency>
    
        </dependencies>
    </project>
    
  2. application.yml

    server:
      port: 9014
    spring:
      application:
        name: tensquare-crawler
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.136.104:3306/tensquare_article?characterEncoding=UTF8
        username: root
        password: 123456
      jpa:
        database: mysql
        show-sql: true
      redis:
        host: 192.168.136.104
    
  3. 啓動類

    package com.tensquare.crawler;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import us.codecraft.webmagic.scheduler.RedisScheduler;
    import util.IdWorker;
    
    @EnableScheduling
    @SpringBootApplication
    public class CrawlerApplication {
    
        @Value("${spring.redis.host}")
        private String REDIS_HOST;
    
        public static void main(String[] args) {
            SpringApplication.run(CrawlerApplication.class, args);
        }
    
        @Bean
        public IdWorker idWorker() {
            return new IdWorker(1, 11);
        }
    
        @Bean
        public RedisScheduler redisScheduler() {
            return new RedisScheduler(REDIS_HOST);
        }
    }
    
  4. 複製文章實體類以及數據訪問接口(省略)

爬取類(PageProcessor)

package com.tensquare.crawler.processor;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;

/**
 * 文章爬取類
 */
@Component
public class ArticleProcessor implements PageProcessor {

    @Override
    public void process(Page page) {
        // 添加爬取的頁面
        page.addTargetRequests(page.getHtml()
                .links().regex("https://blog.csdn.net/[a-z 0-9-]+/article/details/[0-9]{8}").all());
        // 獲取標題以及內容
        String title = page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[1]/div/div/div[1]/h1/text()").get();
        String content = page.getHtml().xpath("//*[@id=\"article_content\"]").get();
        if (StringUtils.isNotBlank(title) && StringUtils.isNotBlank(content)) {
            page.putField("title", title);
            page.putField("content", content);
        } else {
            page.setSkip(true);
        }
    }

    @Override
    public Site getSite() {
        return Site.me().setRetryTimes(100).setSleepTime(100);
    }
}

入庫類(Pipeline)

package com.tensquare.crawler.pipeline;

import com.tensquare.crawler.dao.ArticleDao;
import com.tensquare.crawler.pojo.Article;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;
import util.IdWorker;

@Component
public class ArticlePipeline implements Pipeline {

    @Autowired
    private ArticleDao articleDao;
    
    @Autowired
    private IdWorker idWorker;
    
    private String channelId;

    public void setChannelId(String channelId) {
        this.channelId = channelId;
    }

    @Override
    public void process(ResultItems resultItems, Task task) {
        // 取出爬取類中的title和content
        String title = resultItems.get("title");
        String content = resultItems.get("content");
        // 構造文章對象
        Article article = new Article();
        article.setChannelid(channelId);
        article.setId(idWorker.nextId().toString());
        article.setTitle(title);
        article.setContent(content);
        // 保存
        articleDao.save(article);
    }
}

任務(Task)

package com.tensquare.crawler.task;

import com.tensquare.crawler.pipeline.ArticlePipeline;
import com.tensquare.crawler.processor.ArticleProcessor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.scheduler.RedisScheduler;

@Slf4j
@Component
public class ArticleCrawlerTask {

    @Autowired
    private ArticlePipeline articlePipeline;

    @Autowired
    private RedisScheduler redisScheduler;

    @Autowired
    private ArticleProcessor articleProcessor;

    @Scheduled(cron = "0 0 0 * * *")
    public void aiTask() {
        log.info("開始爬取AI文章");
        articlePipeline.setChannelId("ai");
        Spider spider = Spider.create(articleProcessor);
        spider.addUrl("https://blog.csdn.net/nav/ai/")
                .addPipeline(articlePipeline)
                .setScheduler(redisScheduler)
                .start();
    }

    @Scheduled(cron = "0 0 1 * * *")
    public void blockChainTask() {
        log.info("開始爬取區塊鏈文章");
        articlePipeline.setChannelId("blockchain");
        Spider spider = Spider.create(articleProcessor);
        spider.addUrl("https://blog.csdn.net/nav/blockchain/")
                .addPipeline(articlePipeline)
                .setScheduler(redisScheduler)
                .run();
    }

    @Scheduled(cron = "0 0 2 * * *")
    public void dbTask() {
        log.info("開始爬取區數據庫文章");
        articlePipeline.setChannelId("db");
        Spider spider = Spider.create(articleProcessor);
        spider.addUrl("https://blog.csdn.net/nav/db/")
                .addPipeline(articlePipeline)
                .setScheduler(redisScheduler)
                .run();
    }

    @Scheduled(cron = "0 0 3 * * *")
    public void langTask() {
        log.info("開始爬取編程語言文章");
        articlePipeline.setChannelId("lang");
        Spider spider = Spider.create(articleProcessor);
        spider.addUrl("https://blog.csdn.net/nav/lang/")
                .addPipeline(articlePipeline)
                .setScheduler(redisScheduler)
                .run();
    }

    @Scheduled(cron = "0 0 4 * * *")
    public void newsTask() {
        log.info("開始爬取資訊文章");
        articlePipeline.setChannelId("news");
        Spider spider = Spider.create(articleProcessor);
        spider.addUrl("https://blog.csdn.net/nav/news/")
                .addPipeline(articlePipeline)
                .setScheduler(redisScheduler)
                .run();
    }

    @Scheduled(cron = "0 0 5 * * *")
    public void webTask() {
        log.info("開始爬取前端文章");
        articlePipeline.setChannelId("web");
        Spider spider = Spider.create(articleProcessor);
        spider.addUrl("https://blog.csdn.net/nav/web/")
                .addPipeline(articlePipeline)
                .setScheduler(redisScheduler)
                .run();
    }


}

注意:addUrl(url)中添加的路徑一定要以/結尾。

十次方用戶數據爬取

從csdn中爬取用戶暱稱和頭像,存到用戶表,頭像圖片存儲到本地。

用戶爬取微服務

創建Module

  1. pom.xml(省略,與文章數據爬取微服務一致)

  2. application.yml

    server:
      port: 9015
    spring:
      application:
        name: tensquare-user-crawler
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.136.104:3306/tensquare_user?characterEncoding=UTF8
        username: root
        password: 123456
      jpa:
        database: mysql
        show-sql: true
      redis:
        host: 192.168.136.104
    
  3. 啓動類

    package com.tensquare.crawler;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import us.codecraft.webmagic.scheduler.RedisScheduler;
    import util.IdWorker;
    
    @EnableScheduling
    @SpringBootApplication
    public class UserCrawlerApplication {
    
        @Value("${spring.redis.host}")
        private String REDIS_HOST;
    
        public static void main(String[] args) {
            SpringApplication.run(UserCrawlerApplication.class, args);
        }
    
        @Bean
        public IdWorker idWorker() {
            return new IdWorker(1, 11);
        }
    
        @Bean
        public RedisScheduler redisScheduler() {
            return new RedisScheduler(REDIS_HOST);
        }
    }
    
  4. 複製用戶實體類以及數據訪問接口(省略)

下載工具類

tensquare_common中添加下載工具類

package util;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;

/**
 * 下載工具類
 */
public class DownloadUtil {

    /**
     * 下載
     * 
     * @param urlStr
     * @param filename
     * @param savePath
     * @throws IOException
     */
    public static void download(String urlStr, String filename, String
            savePath) throws IOException {
        URL url = new URL(urlStr);
        //打開url連接
        URLConnection connection = url.openConnection();
        //請求超時時間
        connection.setConnectTimeout(5000);
        //輸入流
        InputStream in = connection.getInputStream();
        //緩衝數據
        byte[] bytes = new byte[1024];
        //數據長度
        int len;
        //文件
        File file = new File(savePath);
        if (!file.exists())
            file.mkdirs();
        OutputStream out = new
                FileOutputStream(file.getPath() + "\\" + filename);
        //先讀到bytes中
        while ((len = in.read(bytes)) != -1){
        //再從bytes中寫入文件
            out.write(bytes, 0, len);
        }
        //關閉IO
        out.close();
        in.close();
    }
}

爬取類(PageProcessor)

package com.tensquare.crawler.processor;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;

@Component
public class UserProcessor implements PageProcessor {

    @Override
    public void process(Page page) {
        // 添加爬取的頁面
        page.addTargetRequests(page.getHtml().links().regex("https://blog.csdn.net/[a-z 0-9-]+/article/details/[0-9]{8}").all());
        // 暱稱和頭像
        String nickname = page.getHtml().xpath("//*[@id=\"uid\"]/text()").get();
        String image = page.getHtml().xpath("//*[@id=\"asideProfile\"]/div[1]/div[1]/a/img[1]").get();
        // 保存
        if (StringUtils.isNotBlank(nickname) && StringUtils.isNotBlank(image)) {
            page.putField("nickname", nickname);
            page.putField("image", image);
        } else {
            page.setSkip(true);
        }

    }

    @Override
    public Site getSite() {
        return Site.me().setRetryTimes(3000).setSleepTime(100);
    }
}

入庫類(Pipeline)

package com.tensquare.crawler.pipeline;

import com.tensquare.crawler.dao.UserDao;
import com.tensquare.crawler.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;
import util.DownloadUtil;
import util.IdWorker;

import java.io.IOException;

@Slf4j
@Component
public class UserPipeline implements Pipeline {


    @Autowired
    private UserDao userDao;

    @Autowired
    private IdWorker idWorker;

    @Override
    public void process(ResultItems resultItems, Task task) {
        // 取出nickname和image
        String nickname = resultItems.get("nickname").toString();
        String image = resultItems.get("image").toString();

        User user = new User();
        user.setId(idWorker.nextId().toString());
        user.setNickname(nickname);
        String fileName = image.substring(image.lastIndexOf("/") + 1, image.lastIndexOf(" ") - 1);
        user.setAvatar(fileName);
        userDao.save(user);

        // 下載圖片
        try {
            String url = image.substring(image.indexOf("https://"), image.lastIndexOf(" ") - 1);
            DownloadUtil.download(url, fileName, "E:/userImage");
        } catch (IOException e) {
            log.error("下載文件發生異常!e = ", e);
        }

    }
}

任務類(Task)

package com.tensquare.crawler.task;

import com.tensquare.crawler.pipeline.UserPipeline;
import com.tensquare.crawler.processor.UserProcessor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.scheduler.RedisScheduler;

/**
 * 用戶數據爬取類
 */
@Slf4j
@Component
public class UserCrawlerTask {

    @Autowired
    private UserProcessor userProcessor;

    @Autowired
    private UserPipeline userPipeline;

    @Autowired
    private RedisScheduler redisScheduler;

    @Scheduled(cron = "0 0 6 * * *")
    public void userTask () {
        log.info("開始爬取用戶數據");
        Spider spider = Spider.create(userProcessor);
        spider.addUrl("https://blog.csdn.net/")
                .addPipeline(userPipeline)
                .setScheduler(redisScheduler)
                .start();
    }

}

注意:addUrl方法以/結尾

爬取效果

文章數據

用戶數據

用戶數據

用戶頭像

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章