java爬虫抓取网页数据(Java开发的爬虫框架很容易上手,输出结果:如果你和我一样)

优采云 发布时间: 2021-11-25 01:16

  java爬虫抓取网页数据(Java开发的爬虫框架很容易上手,输出结果:如果你和我一样)

  对于初学者来说,WebMagic 作为 Java 开发的爬虫框架很容易使用。我们通过一个简单的例子来了解一下。

  WebMagic 框架介绍

  WebMagic 框架收录四个组件,PageProcessor、Scheduler、Downloader 和 Pipeline。

  这四个组件分别对应爬虫生命周期中的处理、管理、下载、持久化功能。

  这四个组件是Spider中的属性,爬虫框架由Spider启动和管理。

  WebMagic 的整体结构如下:

  

  四大组件

  PageProcessor 负责解析页面、提取有用信息和发现新链接。您需要自己定义它。

  Scheduler 负责管理要爬取的 URL 和一些重复数据删除工作。一般不需要自己自定义Scheduler。

  Pipeline 负责提取结果的处理,包括计算、持久化到文件、数据库等。

  Downloader 负责从网上下载页面进行后续处理。通常,您不需要自己实现它。

  用于数据流的对象

  Request是对URL地址的一层封装,一个Request对应一个URL地址。

  Page 代表从 Downloader 下载的页面——可以是 HTML、JSON 或其他文本格式的内容。

  ResultItems相当于一个Map,保存PageProcessor处理的结果,供Pipeline使用。

  环境配置

  使用Maven添加依赖的jar包。

  

us.codecraft

webmagic-core

0.7.3

  

us.codecraft

webmagic-extension

0.7.3

org.slf4j

slf4j-log4j12

  或者直接点我下载。

  添加jar包之后,所有的准备工作就完成了,是不是很简单?

  下面我们来测试一下。

  package edu.heu.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;

/**

* @ClassName: MyCnblogsSpider

* @author LJH

* @date 2017年11月26日 下午4:41:40

*/

public class MyCnblogsSpider implements PageProcessor {

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

public Site getSite() {

return site;

}

public void process(Page page) {

if (!page.getUrl().regex("http://www.cnblogs.com/[a-z 0-9 -]+/p/[0-9]{7}.html").match()) {

page.addTargetRequests(

page.getHtml().xpath("//*[@id=\"mainContent\"]/div/div/div[@class=\"postTitle\"]/a/@href").all());

} else {

page.putField(page.getHtml().xpath("//*[@id=\"cb_post_title_url\"]/text()").toString(),

page.getHtml().xpath("//*[@id=\"cb_post_title_url\"]/@href").toString());

}

}

public static void main(String[] args) {

Spider.create(new MyCnblogsSpider()).addUrl("http://www.cnblogs.com/justcooooode/")

.addPipeline(new ConsolePipeline()).run();

}

}

  输出结果:

  

  如果你和我一样,之前没有使用过 log4j,可能会出现以下警告:

  

  这是因为缺少配置文件。在资源目录新建一个log4j.properties文件,粘贴下面的配置信息。

  该目录可以定义为您自己的文件夹。

  # 全局日志级别设定 ,file

log4j.rootLogger=INFO, stdout, file

# 自定义包路径LOG级别

log4j.logger.org.quartz=WARN, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{MM-dd HH:mm:ss}[%p]%m%n

# Output to the File

log4j.appender.file=org.apache.log4j.FileAppender

log4j.appender.file.File=D:\\MyEclipse2017Workspaces\\webmagic\\webmagic.log

log4j.appender.file.layout=org.apache.log4j.PatternLayout

log4j.appender.file.layout.ConversionPattern=%n%-d{MM-dd HH:mm:ss}-%C.%M()%n[%p]%m%n

  立即尝试,没有警告。

  爬取列表类 网站 示例

  列表爬取的思路非常相似。首先判断是否是列表页。如果是,将 文章 url 添加到抓取队列中。如果不是,说明此时是一个文章页面,直接爬取你想要的。内容很好。

  选择列表类型 文章 网站:

  

  首先判断是文章还是列表。查看几页后,可以找到规则并使用正则表达式进行区分。

  page.getUrl().regex("https://voice\\.hupu\\.com/nba/[0-9]{7}\\.html").match()

  如果满足上述正则表达式,则该url对应一个文章页面。

  接下来提取需要爬取的内容,我选择了xPath(浏览器自带,可以直接粘贴)。

  

  WebMagic 框架支持多种提取方式,包括xPath、css 选择器、正则表达式,所有链接都可以通过links() 方法进行选择。

  提取前记得通过getHtml()获取html对象,通过html对象使用提取方法。

  ps:WebMagic 似乎不支持 xPath 中的 last() 方法。如果你使用它,你可以考虑其他方法。

  然后使用 page.putFiled(String key, Object field) 方法将你想要的内容放入一个键值对中。

  page.putField("Title", page.getHtml().xpath("/html/body/div[4]/div[1]/div[1]/h1/text()").toString());

page.putField("Content", page.getHtml().xpath("/html/body/div[4]/div[1]/div[2]/div/div[2]/p/text()").all().toString());

  如果文章页面的规律性不满足,说明这是一个列表页面。这时候页面中文章的url必须通过xPath来定位。

  

  page.getHtml().xpath("/html/body/div[3]/div[1]/div[2]/ul/li/div[1]/h4/a/@href").all();

  这时候就已经得到了要爬取的url列表,可以通过addTargetRequests方法将它们加入到队列中。

  最后实现翻页。同理,WebMagic 会自动加入爬取队列。

  

  page.getHtml().xpath("/html/body/div[3]/div[1]/div[3]/a[@class='page-btn-prev']/@href").all()

  以下是完整代码。我自己实现了一个 MysqlPipeline 类。使用Mybatis时,可以将抓取到的数据直接持久化到数据库中。

  您还可以使用内置的 ConsolePipeline 或 FilePipeline 等。

  package edu.heu.spider;

import java.io.IOException;

import java.io.InputStream;

import java.util.Iterator;

import java.util.Map;

import java.util.Map.Entry;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import edu.heu.domain.News;

import us.codecraft.webmagic.Page;

import us.codecraft.webmagic.ResultItems;

import us.codecraft.webmagic.Site;

import us.codecraft.webmagic.Spider;

import us.codecraft.webmagic.Task;

import us.codecraft.webmagic.pipeline.Pipeline;

import us.codecraft.webmagic.processor.PageProcessor;

/**

* @ClassName: HupuNewsSpider

* @author LJH

* @date 2017年11月27日 下午4:54:48

*/

public class HupuNewsSpider implements PageProcessor {

// 抓取网站的相关配置,包括编码、抓取间隔、重试次数等

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

public Site getSite() {

return site;

}

public void process(Page page) {

// 文章页,匹配 https://voice.hupu.com/nba/七位数字.html

if (page.getUrl().regex("https://voice\\.hupu\\.com/nba/[0-9]{7}\\.html").match()) {

page.putField("Title", page.getHtml().xpath("/html/body/div[4]/div[1]/div[1]/h1/text()").toString());

page.putField("Content",

page.getHtml().xpath("/html/body/div[4]/div[1]/div[2]/div/div[2]/p/text()").all().toString());

}

// 列表页

else {

// 文章url

page.addTargetRequests(

page.getHtml().xpath("/html/body/div[3]/div[1]/div[2]/ul/li/div[1]/h4/a/@href").all());

// 翻页url

page.addTargetRequests(

page.getHtml().xpath("/html/body/div[3]/div[1]/div[3]/a[@class='page-btn-prev']/@href").all());

}

}

public static void main(String[] args) {

Spider.create(new HupuNewsSpider()).addUrl("https://voice.hupu.com/nba/1").addPipeline(new MysqlPipeline())

.thread(3).run();

}

}

// 自定义实现Pipeline接口

class MysqlPipeline implements Pipeline {

public MysqlPipeline() {

}

public void process(ResultItems resultitems, Task task) {

Map mapResults = resultitems.getAll();

Iterator iter = mapResults.entrySet().iterator();

Map.Entry entry;

// 输出到控制台

while (iter.hasNext()) {

entry = iter.next();

System.out.println(entry.getKey() + ":" + entry.getValue());

}

// 持久化

News news = new News();

if (!mapResults.get("Title").equals("")) {

news.setTitle((String) mapResults.get("Title"));

news.setContent((String) mapResults.get("Content"));

}

try {

InputStream is = Resources.getResourceAsStream("conf.xml");

SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);

SqlSession session = sessionFactory.openSession();

session.insert("add", news);

session.commit();

session.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

  查看数据库:

  

  爬取的数据一直静静地躺在数据库中。

  官方文档还介绍了通过注解实现各种功能,非常简单灵活。

  使用xPath时要注意,框架作者自定义了几个功能:

  表达式描述XPath1.0

  文字(n)

  第n个直接文本子节点,0表示全部

  纯文本

  所有文本()

  所有直接和间接文本子节点

  不支持

  整洁的文本()

  所有直接和间接文本子节点,并用换行符替换一些标签,使纯文本显示更整洁

  不支持

  html()

  内部html,不包括标签的html本身

  不支持

  外层Html()

  内部html,包括标签的html本身

  不支持

  正则表达式(@attr,expr,group)

  这里@attr 和 group 都是可选的,默认是 group0

  不支持

  使用起来非常方便。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线