文档章节

爬虫入门(WebMagic Scrapy )

liangxiao
 liangxiao
发布于 07/01 14:15
字数 1607
阅读 9
收藏 0

爬虫架构

WebMagic的四个组件 1.Downloader Downloader负责从互联网上下载页面,以便后续处理。WebMagic默认使用了Apache HttpClient作为下载工具。

2.PageProcessor PageProcessor负责解析页面,抽取有用信息,以及发现新的链接。WebMagic使用Jsoup作为HTML解析工具,并基于其开发了解析XPath的工具Xsoup。

在这四个组件中,PageProcessor对于每个站点每个页面都不一样,是需要使用者定制的部分。

3.Scheduler Scheduler负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重。也支持使用Redis进行分布式管理。

除非项目有一些特殊的分布式需求,否则无需自己定制Scheduler。

4.Pipeline Pipeline负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。

Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。对于一类需求一般只需编写一个Pipeline。

代码示例

Webmagic

爬的是虎嗅的文章

pom依赖

<!-- webmagic 网络爬虫jar -->
		<dependency>
			<groupId>us.codecraft</groupId>
			<artifactId>webmagic-extension</artifactId>
			<version>0.7.3</version>
		</dependency>
		<dependency>
		    <groupId>us.codecraft</groupId>
		    <artifactId>webmagic-core</artifactId>
		    <version>0.7.3</version>
		</dependency>

Main

package com.jinguanjia.app.exercise.spider;

import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.proxy.Proxy;
import us.codecraft.webmagic.proxy.SimpleProxyProvider;

/**
 * @author fengpuchao
 * @date 2019年7月1日
 */
public class Main {

	public static void main(String[] args){
		SimpleHttpClientDownloader httpClientDownloader = new SimpleHttpClientDownloader();
		httpClientDownloader.setProxyProvider(
				SimpleProxyProvider.from(new Proxy("101.101.101.101", 8888), new Proxy("102.102.102.102", 8888)));
		    
		//设置处理器
		Spider.create(new HuXiuPageProcessor())
		//设置其实url
		.addUrl("https://www.huxiu.com")
		//处理数据的pipeline
		.addPipeline(new DataHandlerPipeline())
		//下載器  設置代理
//		.setDownloader(httpClientDownloader)
		//調度用的,可以處理url
//		.setScheduler(scheduler)
		// 设置线程数
		.thread(5)
		.run();
		
	}

}

HuXiuPageProcessor

package com.jinguanjia.app.exercise.spider;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.downloader.HttpClientDownloader;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.proxy.Proxy;
import us.codecraft.webmagic.proxy.SimpleProxyProvider;

/**
 * @author fengpuchao
 * @date 2019年7月1日
 */
public class HuXiuPageProcessor implements PageProcessor {
	
	/**
	 * 设置抓取网站的相关配置
	 * 重试3次
	 * 1s中抓取一次
	 */
	private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
	

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

	@Override
	public void process(Page page) {
		
		/**
		 * page.getHtml() 提供了很多方法读取内容
		 */
		
		page.addTargetRequests(page.getHtml().links().regex("(https://www.huxiu.com/article/[\\[0-9]+.html)").all());
		page.putField("title", page.getHtml().css("div.wrap-left.pull-left > div.article-wrap > h1","text"));
		if(page.getResultItems().get("title") == null){
			page.setSkip(true);
		}
		page.putField("portal", page.getHtml().css("div.wrap-left.pull-left > div.article-wrap > div.article-img-box > img","src"));
		page.putField("createTime", page.getHtml().css("div.wrap-left.pull-left > div.article-wrap > div.article-author > div > span.article-time.pull-left","text"));
//		page.putField("content", page.getHtml().css("div.article-section-wrap > div.article-section > div.container > div.wrap-left> div.article-wrap > div.article-content-wrap","tidyText"));
		page.putField("content", page.getHtml().xpath("//*[@class='article-content-wrap']//tidyText()"));
		page.putField("images", page.getHtml().css("img","src").all());
	}
	
	
	


}

DataHandlerPipeline

package com.jinguanjia.app.exercise.spider;

import java.util.List;

import org.apache.commons.collections.CollectionUtils;

import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;

/**
 * @author fengpuchao
 * @date 2019年7月1日
 */
public class DataHandlerPipeline implements Pipeline {
	private int count = 0;

	@Override
	public void process(ResultItems item, Task task) {
		try{
			System.out.println("文章标题:" + item.get("title"));
			System.out.println("文章portal:" + item.get("portal"));
			System.out.println("文章创建时间:" + item.get("createTime"));
//			System.out.println("文章内容:" + item.get("content"));
			System.out.println("第几篇文章:" + count ++ );
			List<String> images = (List)item.get("images");
			if(!CollectionUtils.isEmpty(images)){
				for(String str:images){
					ImageDownloader.download(str, System.currentTimeMillis()+ ".jpg", "D://images");
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
		

	}

}

SimpleHttpClientDownloader

package com.jinguanjia.app.exercise.spider;

import us.codecraft.webmagic.downloader.HttpClientDownloader;

/**
 * @author fengpuchao
 * @date 2019年7月1日
 */
public class SimpleHttpClientDownloader extends HttpClientDownloader {

}

ImageDownloader

package com.jinguanjia.app.exercise.spider;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import com.alibaba.druid.util.StringUtils;

/**
 * @author fengpuchao
 * @date 2019年7月2日
 */
public class ImageDownloader {

	public static void download(String netUrl, String filename, String savePath) throws Exception {
		if (StringUtils.isEmpty(netUrl) || StringUtils.isEmpty(filename) || StringUtils.isEmpty(savePath)) {
			return;
		}
		URL url = new URL(netUrl);
		URLConnection con = url.openConnection();
		con.setConnectTimeout(5 * 1000);
		try {
			InputStream is = con.getInputStream();
			// 1K的数据缓冲
			byte[] bs = new byte[1024];
			// 读取到的数据长度
			int len;
			// 输出的文件流
			File sf = new File(savePath);
			if (!sf.exists()) {
				sf.mkdirs();
			}
			OutputStream os = new FileOutputStream(sf.getPath() + "\\" + filename);
			try {
				while ((len = is.read(bs)) != -1) {
					os.write(bs, 0, len);
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (os != null) {
					os.close();
				}
				if (is != null) {
					is.close();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

Scrapy

创建应用

在开始爬取之前,您必须创建一个新的Scrapy项目。 进入您打算存储代码的目录中,运行下列命令:

scrapy startproject my_spider

该命令将会创建包含下列内容的 tutorial 目录:


my_spider/
    scrapy.cfg
    my_spider/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...

这些文件分别是:

  • scrapy.cfg: 项目的配置文件
  • my_spider/: 该项目的python模块。之后您将在此加入代码。
  • my_spider/items.py: 项目中的item文件.
  • my_spider/pipelines.py: 项目中的pipelines文件.
  • my_spider/settings.py: 项目的设置文件.
  • my_spider/spiders/: 放置spider代码的目录.

定义Item

Item 是保存爬取到的数据的容器;其使用方法和python字典类似, 并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。

类似在ORM中做的一样,您可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field 的类属性来定义一个Item。 (如果不了解ORM, 不用担心,您会发现这个步骤非常简单)

首先根据需要从dmoz.org获取到的数据对item进行建模。 我们需要从dmoz中获取名字,url,以及网站的描述。 对此,在item中定义相应的字段。编辑 tutorial 目录中的 items.py 文件:

import scrapy


class MySpiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    name = scrapy.Field()
    title = scrapy.Field()
    info = scrapy.Field()

一开始这看起来可能有点复杂,但是通过定义item, 您可以很方便的使用Scrapy的其他方法。而这些方法需要知道您的item的定义。

创建爬虫

在 spiders 目录下创建文件MainSpider.py ,代码内容如下:

# -*- coding: utf-8 -*-
import scrapy

from my_spider.items import MySpiderItem

class MainSpider(scrapy.Spider):
    # 用于区分别的Spider,名字必须唯一
    name = "itcast"
    # 允许搜索的域名范围
    allowed_domains = ['itcast.com']
    # 启动初始爬取的url
    start_urls = {
        "http://www.itcast.cn/channel/teacher.shtml",
    }
    # 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象
    def parse(self,response):
        items = []

        for each in response.xpath("//div[@class='li_txt']"):
            # 将我们得到的数据封装到一个 `ItcastItem` 对象
            item = MySpiderItem()
            # extract()方法返回的都是unicode字符串
            name = each.xpath("h3/text()").extract()
            title = each.xpath("h4/text()").extract()
            info = each.xpath("p/text()").extract()

            # xpath返回的是包含一个元素的列表
            item['name'] = name[0]
            item['title'] = title[0]
            item['info'] = info[0]

            items.append(item)

        # 直接返回最后数据
        return items

settings.py文件设置utf-8编码

ROBOTSTXT_OBEY = False

在 my_spider目录下运行爬虫,输出到 teachers.json 文件中

scrapy crawl itcast -o teachers.json

源代码参见:scrapy示例

参考文档

WebMagic

Scrapy 入门教程

Scrapy入门教程

© 著作权归作者所有

上一篇: 网联支付
下一篇: Java 的SPI机制
liangxiao
粉丝 22
博文 351
码字总数 137029
作品 0
杭州
后端工程师
私信 提问
webmagic的设计机制及原理-如何开发一个Java爬虫

此文章是webmagic 0.1.0版的设计手册,后续版本的入门及用户手册请看这里:https://github.com/code4craft/webmagic/blob/master/user-manual.md 之前就有网友在博客里留言,觉得webmagic的实...

黄亿华
2013/07/20
67.8K
94
webmagic 0.2.0 发布,Java垂直爬虫框架

此次更新的主题是"方便"(之前的主题是"灵活")。 增加了webmagic-extension模块。 增加了注解方式支持,可以通过POJO+注解的方式编写一个爬虫,更符合Java开发习惯。以下是抓取oschina博客的完...

黄亿华
2013/08/12
5.1K
22
玩转webmagic代码之Scheduler

webmagic上线之后,因为灵活性很强,得到了一些爬虫老手的欢迎,但是对于新手来说可能稍微摸不着头脑,我的需求是这样子,什么模块化,什么灵活性,但是看了半天,我也不知道怎么解决我的问题...

黄亿华
2013/08/21
13.8K
10
初步框架方案

此项目核心分三块(爬虫引擎,数据存储,web界面以及restful api) 爬虫引擎 采用webmagic作为框架 webmagic的是一个无须配置、便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即...

OSC闲人
2016/01/22
3
0
WebMagic 0.4.1 发布,Java 爬虫框架

此次更新加强了Ajax抓取的功能,并进行了一些功能改进。同时引入了重要的脚本化功能"webmagic-script",为今后的WebMagic-Avalon计划做准备。 功能增强: 修复了抓取完页面后,Spider偶尔无法...

黄亿华
2013/11/28
3.3K
17

没有更多内容

加载失败,请刷新页面

加载更多

数据安全管理:RSA算法,签名验签流程详解

本文源码:GitHub·点这里 || GitEE·点这里 一、RSA算法简介 1、加密解密 RSA加密是一种非对称加密,在公开密钥加密和电子商业中RSA被广泛使用。可以在不直接传递密钥的情况下,完成加解密操...

知了一笑
22分钟前
2
0
Podman 使用指南

> 原文链接:Podman 使用指南 Podman 原来是 CRI-O 项目的一部分,后来被分离成一个单独的项目叫 libpod。Podman 的使用体验和 Docker 类似,不同的是 Podman 没有 daemon。以前使用 Docker...

米开朗基杨
今天
6
0
拯救 项目经理个人时间的5个技巧

优秀的项目经理都有一个共同点,那就是良好的时间管理能力。专业的项目经理会确保他们的时间投入富有成效,尽可能避免时间浪费。 时间管理叫做GTD,即Getting Things Done——“把事情做完”...

Airship
今天
7
0
LNMP环境介绍,Mariadb安装,服务管理,mariadb安装3

LNMP环境介绍 Nginx 处理的请求有两种,分为 静态与动态 图片,js,css,视频,音频,flash 等都是静态请求,这些数据都不是保存在数据库里面的 动态请求一般来说,需要的数据是在数据库里面...

doomcat
今天
3
0
前端技术之:Prisma Demo服务部署过程记录

安装前提条件: 1、已经安装了docker运行环境 2、以下命令执行记录发生在MackBook环境 3、已经安装了PostgreSQL(我使用的是11版本) 4、Node开发运行环境可以正常工作 首先需要通过Node包管...

popgis
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部