关于java:使用-Java使用WebMagic-爬取网站

5次阅读

共计 4648 个字符,预计需要花费 12 分钟才能阅读完成。

小小又开始学习了,这次跟着我的项目学习着,须要应用一个相干的爬虫,这里应用的是 webmagic 作为网站的爬虫。

装置

这里应用 maven 进行装置。
依据 maven 下载相干的包

<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>

Hello World

简直所有的 api 的学习,都是从 hello world 开始的,webmagic 也不例外,应用的同样也是 hello world 案例。
以爬取 sina 博文为例。
复制以下代码

package com.example.demo;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;

public class SinaBlogProcessor implements PageProcessor {

  public static final String URL_LIST = "http://blog\\.sina\\.com\\.cn/s/articlelist_1487828712_0_\\d+\\.html";

  public static final String URL_POST = "http://blog\\.sina\\.com\\.cn/s/blog_\\w+\\.html";

  private Site site = Site
          .me()
          .setDomain("blog.sina.com.cn")
          .setSleepTime(3000)
          .setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");

  @Override
  public void process(Page page) {
    // 列表页
    if (page.getUrl().regex(URL_LIST).match()) {page.addTargetRequests(page.getHtml().xpath("//div[@class=\"articleList\"]").links().regex(URL_POST).all());
      page.addTargetRequests(page.getHtml().links().regex(URL_LIST).all());
      // 文章页
    } else {page.putField("title", page.getHtml().xpath("//div[@class='articalTitle']/h2"));
      page.putField("content", page.getHtml().xpath("//div[@id='articlebody']//div[@class='articalContent']"));
      page.putField("date",
              page.getHtml().xpath("//div[@id='articlebody']//span[@class='time SG_txtc']").regex("\\((.*)\\)"));
    }
  }

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

  public static void main(String[] args) {Spider.create(new SinaBlogProcessor()).addUrl("http://blog.sina.com.cn/s/articlelist_1487828712_0_1.html")
            .run();}
}

查看相干运行后果

这里就等于说曾经运行胜利,爬取到了一些数据

PageProcessor

这里用于实现相干的配置。

代码如下

public class GithubRepoPageProcessor implements PageProcessor {

    // 局部一:抓取网站的相干配置,包含编码、抓取距离、重试次数等
    private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);

    @Override
    // process 是定制爬虫逻辑的外围接口,在这里编写抽取逻辑
    public void process(Page page) {
        // 局部二:定义如何抽取页面信息,并保留下来
        page.putField("author", page.getUrl().regex("https://github\\.com/(\\w+)/.*").toString());
        page.putField("name", page.getHtml().xpath("//h1[@class='entry-title public']/strong/a/text()").toString());
        if (page.getResultItems().get("name") == null) {
            //skip this page
            page.setSkip(true);
        }
        page.putField("readme", page.getHtml().xpath("//div[@id='readme']/tidyText()"));

        // 局部三:从页面发现后续的 url 地址来抓取
        page.addTargetRequests(page.getHtml().links().regex("(https://github\\.com/[\\w\\-]+/[\\w\\-]+)").all());
    }

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

    public static void main(String[] args) {Spider.create(new GithubRepoPageProcessor())
                // 从 "https://github.com/code4craft" 开始抓
                .addUrl("https://github.com/code4craft")
                // 开启 5 个线程抓取
                .thread(5)
                // 启动爬虫
                .run();}
}

抽取元素

这里应用相干的办法抽取元素。

 这里应用相干的办法抽取相干的元素
List<String> urls = page.getHtml().css("div.pagination").links().regex(".*/search/\?l=java.*").all();

保留后果

这里保留后果应用 Pipeline 办法

public static void main(String[] args) {Spider.create(new GithubRepoPageProcessor())
            // 从 "https://github.com/code4craft" 开始抓
            .addUrl("https://github.com/code4craft")
            .addPipeline(new JsonFilePipeline("D:\\webmagic\\"))
            // 开启 5 个线程抓取
            .thread(5)
            // 启动爬虫
            .run();}

理论案例

这里以 http://blog.sina.com.cn/flash… 作为例子,在这个例子里,要从最终的博客文章页面,抓取博客的题目,内容,和日期。

列表页

列表页的格局为 http://blog.sina.com.cn/s/art… 这里 0 和 1 都是可变的页数。

文章页

文章页的格局是,http://blog.sina.com.cn/s/blo… 这里,最初一段是可变的字符串,为文章的 id

进行正则匹配

这里用两个正则进行匹配。
这里用,xpath//div[@class=\”articleList\”] 进行相干的匹配,

所以,能够这样进行匹配

page.addTargetRequests(page.getHtml().xpath("//div[@class=\"articleList\"]").links().regex("http://blog\\.sina\\.com\\.cn/s/blog_\\w+\\.html").all());
page.addTargetRequests(page.getHtml().links().regex("http://blog\\.sina\\.com\\.cn/s/articlelist_1487828712_0_\\d+\\.html").all());

内容的增加

这里再进行一次内容的增加

page.putField("title", page.getHtml().xpath("//div[@class='articalTitle']/h2"));
page.putField("content", page.getHtml().xpath("//div[@id='articlebody']//div[@class='articalContent']"));
page.putField("date",
        page.getHtml().xpath("//div[@id='articlebody']//span[@class='time SG_txtc']").regex("\\((.*)\\)"));

辨别列表和指标页

这里,进行辨别列表页,和指标页。

// 列表页
if (page.getUrl().regex(URL_LIST).match()) {page.addTargetRequests(page.getHtml().xpath("//div[@class=\"articleList\"]").links().regex(URL_POST).all());
    page.addTargetRequests(page.getHtml().links().regex(URL_LIST).all());
    // 文章页
} else {page.putField("title", page.getHtml().xpath("//div[@class='articalTitle']/h2"));
    page.putField("content", page.getHtml().xpath("//div[@id='articlebody']//div[@class='articalContent']"));
    page.putField("date",
            page.getHtml().xpath("//div[@id='articlebody']//span[@class='time SG_txtc']").regex("\\((.*)\\)"));
}

这样就实现了最根本例子的读取。

正文完
 0