架构及简介

Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛。

Scrapy 使用了 Twisted(其主要对手是Tornado)异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求。

Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。

Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。

Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,

Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器),

Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.

Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。

Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)

开发流程

开发一个简单爬虫步骤:

  • 新建项目
scrapy startproject demo
  • 编写spider

    • 种子url (请求)
    • 解析方法
  • 编写item

    结果数据模型

  • 持久化

    编写pipelines

生成目录介绍

scrapy.cfg :项目的配置文件

mySpider/ :项目的Python模块,将会从这里引用代码

mySpider/items.py :项目的目标文件

mySpider/pipelines.py :项目的管道文件

mySpider/settings.py :项目的设置文件

mySpider/spiders/ :存储爬虫代码目录

使用命令创建爬虫类

scrapy genspider gitee "gitee.com"

解析

通常我们解析都会涉及到 xpath csspath 正则,有的时候可能还有jsonpath(python中json访问基本不用使用复杂的jsonpath,字典访问就可以)

scrapy 内置xpath和csspath支持

Selector

而解析器本身也可以单独使用

  • xpath()
  • extract_first()
  • extract() #返回一个列表
  • 索引访问,因为scrapy.selector.unified.SelectorList继承list,可以通过索引访问
from scrapy import Selector

if __name__ == '__main__':
body = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>hello</p>
<p class="big">hello</p>
</body>
</html>"""
s = Selector(text=body)
title=s.xpath("//title/text()").extract_first();#抽取
print(title)
#Title
pe = s.xpath("//p")
print(s.xpath("//p").extract())
#['<p>hello</p>', '<p class="big">hello</p>']
print(pe)
#[<Selector xpath='//p' data='<p>hello</p>'>, <Selector xpath='//p' data='<p class="big">hello</p>'>]
print(type(pe))
#<class 'scrapy.selector.unified.SelectorList'>
print(type(pe[0])) #通过索引访问
#<class 'scrapy.selector.unified.Selector'>
print(type(pe.pop()))
#<class 'scrapy.selector.unified.Selector'>
p=s.xpath("//p").extract_first()
print(p)
  • css()

    css选择器我们::text选择内容,用::attr() 选择属性
print(s.css("title").extract_first())
print(s.css("title::text").extract_first())
print(s.css("title::text").extract())
print(s.css("p.big::text").extract_first())
print(s.css("p.big::attr(class)").extract_first()) # <title>Title</title>
# Title
# ['Title']
# hello big
# big
  • css()和xpath()混用

    scrapy.selector.unified.SelectorList scrapy.selector.unified.Selector 本身有css和xpath方法,所以可以组合使用
print(s.xpath("//body").css("p.big").extract_first())
print(s.css("body").xpath("//p[@class='big']").extract_first()) # <p class="big">hello big </p>
# <p class="big">hello big </p>
  • re()和re_first()

    scrapy.selector.unified.SelectorList scrapy.selector.unified.Selector 拥有 re()方法,支持通过正则来过滤
print(s.xpath("//p/text()").re_first("big"))
print(type(s.xpath("//p/text()").re("big"))) # big
# <class 'list'>

** 但re()返回列表,.re_first返回str,所以不能再继续调用其他的选择方法

在爬虫中使用解析器

response对象已经

class GiteeSpider(scrapy.Spider):
name = 'gitee'
allowed_domains = ['gitee.com']
start_urls = ['https://gitee.com/haimama'] def parse(self, response):
print(type(response))
t=response.xpath("//title/text()").extract_first()
print(t) ##启动爬虫执行后的结果
# 执行结果省略日志
# <class 'scrapy.http.response.html.HtmlResponse'>
# 码马 (haimama) - Gitee

response对象类型为 scrapy.http.response.html.HtmlResponse,该类继承TextResponse 。拥有xpath()和css()方法如下

所以response 可以直接使用前文中的Selector 的方式来解析

    def xpath(self, query, **kwargs):
return self.selector.xpath(query, **kwargs) def css(self, query):
return self.selector.css(query)

启动爬虫

在爬虫目录编写run.py方法,添加如下脚本,这样就可以直接执行爬虫了。如果命令行执行的话scrapy crawl gitee。其中gitee为爬虫名,对应GiteeSpider中的name字段

# coding: utf-8

from scrapy import cmdline
if __name__ == '__main__':
cmdline.execute("scrapy crawl gitee".split()) # scrapy crawl gitee

完整参考代码 https://gitee.com/haimama/scrapy_demo001

xpath参考 我的博客python使用xpath

scrapy和scrapy-redis 详解一 入门demo及内容解析的更多相关文章

  1. Redis详解入门篇

    Redis详解入门篇 [本教程目录] 1.redis是什么2.redis的作者3.谁在使用redis4.学会安装redis5.学会启动redis6.使用redis客户端7.redis数据结构 – 简介 ...

  2. Redis详解入门篇(转载)

    Redis详解入门篇(转载) [本教程目录] 1.redis是什么2.redis的作者3.谁在使用redis4.学会安装redis5.学会启动redis6.使用redis客户端7.redis数据结构 ...

  3. 基础拾遗------redis详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  4. Spring Data操作Redis详解

    Spring Data操作Redis详解 Redis是一种NOSQL数据库,Key-Value形式对数据进行存储,其中数据可以以内存形式存在,也可以持久化到文件系统.Spring data对Redis ...

  5. .Net使用Redis详解之ServiceStack.Redis(七) 转载https://www.cnblogs.com/knowledgesea/p/5032101.html

    .Net使用Redis详解之ServiceStack.Redis(七)   序言 本篇从.Net如何接入Reis开始,直至.Net对Redis的各种操作,为了方便学习与做为文档的查看,我做一遍注释展现 ...

  6. ggplot2作图详解:入门函数qplot

    ggplot2作图详解:入门函数qplot   ggplot2的功能不用我们做广告,因为它的作者Hadley Wickham就说ggplot2是一个强大的作图工具,它可以让你不受现有图形类型的限制,创 ...

  7. .Net使用Redis详解之ServiceStack.Redis(7)

    Net使用Redis详解之ServiceStack.Redis(七) 序言 本篇从.Net如何接入Reis开始,直至.Net对Redis的各种操作,为了方便学习与做为文档的查看,我做一遍注释展现,其中 ...

  8. Python基础知识详解 从入门到精通(七)类与对象

    本篇主要是介绍python,内容可先看目录其他基础知识详解,欢迎查看本人的其他文章Python基础知识详解 从入门到精通(一)介绍Python基础知识详解 从入门到精通(二)基础Python基础知识详 ...

  9. Redis详解(二)——AOF

    Redis详解(二)--AOF 前言 RDB 持久化存在一个缺点是一定时间内做一次备份,如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失).对于数据完整性要求很严格的需求 ...

随机推荐

  1. 使用DynamicExpresso实现表达式求值

    之前写了一篇Z.Expressions表达式计算的博客,直到最近才发现Z.Expressions不是免费的.Z.Expressions从2.0开始支持了NetCore,使用一段时期后会提示许可证到期, ...

  2. zabbix安装要求

    zabbix server 和 zabbix Agent都在一个压缩包中,可以从官网上下载源码包,www.zabbix.com/download.php zabbix是C语言编写,压缩包的文件夹介绍: ...

  3. 文本编辑-vi

    命令行模式: 底行模式:

  4. 破晓行动----带你总结JVM的知识大全(二)

    JVM运行时内存 + 垃圾回收与算法

  5. 089 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 使用包进行类管理(1)——创建包

    089 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...

  6. 033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结

    033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结 本文知识点:运算符和表达式知识点总结 前面学习的几篇文都是运算符和表达式相关的知 ...

  7. Arduino读取写入电压值

    读取写入方式分为数字和模拟 读取方式:(注意接地) 数字:digitalRead(pin); 模拟:analogRead(A1);float val=value*(5.0/1023.0);       ...

  8. 【基础】dp系列1

    序列双段最大子段和问题 (也许很水但蒟蒻刚刚学dp就来记录一下) 题目链接 题意就是求序列中的任意两段的最大子段和最大. 我们先预处理出来前缀和,方便求最大子段和. 对于每一个i都求一遍1到i的最大子 ...

  9. Android作业10/07

    1.多个Activity界面实现数据的传递 <?xml version="1.0" encoding="utf-8"?> <androidx. ...

  10. JSOI 2008 【魔兽地图】

    其实这题是我从noip前就开始做的...那个时候打的Pascal,一直TLE,转了C++之后我又写了一遍,A了... 辛酸史:                      题目描述: DotR (Def ...