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

优采云 发布时间: 2022-03-10 18:11

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

  爬虫初学者,WebMagic作为Java开发的爬虫框架很容易上手,下面看一个简单的例子。

  WebMagic 框架简介

  WebMagic 框架由四个组件组成,PageProcessor、Scheduler、Downloader 和 Pipeline。

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

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

  WebMagic的整体架构图如下:

  

  四个组件

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

  Scheduler 负责管理要爬取的 URL,以及一些去重工作。一般不需要自己自定义Scheduler。

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

  下载器负责从 Internet 下载页面以进行后续处理。通常你不需要自己实现它。

  数据流对象

  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());

}

}<br />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=&#39;page-btn-prev&#39;]/@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=&#39;page-btn-prev&#39;]/@href").all());

}

}<br />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,组)

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

  不支持

  使用起来非常方便。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线