scrapy 教程

 

------------------------------------------------------------------------------------------
scrapy 中文文档 和 scrapy 英文文档参照看。因为中文文档比较老,英文文档是最新的。
scrapy 英文文档:https://doc.scrapy.org/en/latest
scrapy 中文文档:http://scrapy-chs.readthedocs.io/zh_CN/1.0/intro/overview.html
高性能爬虫 Scrapy 框架https://www.cnblogs.com/wwg945/articles/9021888.html
------------------------------------------------------------------------------------------
scrapy-redis 配置:https://www.cnblogs.com/wwg945/articles/9046232.html
基于 Scrapy-redis 的分布式爬虫设计:https://www.jianshu.com/p/cd4054bbc757
------------------------------------------------------------------------------------------

Scrapy爬虫入门教程:https://www.jianshu.com/p/43029ea38251
------------------------------------------------------------------------------------------

scarpy 是一个爬虫框架,而 scrapyd 是一个网页版管理 scrapy 的工具, scrapy爬虫写好后,可以用命令行运行,但是如果能在网页上操作就比较方便。 scrapyd 就是为了解决这个问题,能够在网页端查看正在执行的任务,也能新建爬虫任务,和终止爬虫任务,功能比较强大。 还有一个更加强大的国产工具 gerapy
Scrapyd 使用详解:https://blog.csdn.net/fengltxx/article/details/79889340
Gerapy分布式爬虫管理框架:https://cuiqingcai.com/4959.html

scrapy_redis去重优化(已有7亿条数据),附Demo福利:https://blog.csdn.net/bone_ace/article/details/53099042

 

scrapy 框架系列教程:http://www.cnblogs.com/xinyangsdut/p/7628770.html

scrapy 系列教程 - 设置随机 user-agent:https://www.cnblogs.com/cnkai/p/7401343.html

Python分布式爬虫打造搜索引擎Scrapy精讲 系列教程—将bloomfilter(布隆过滤器)集成到scrapy-redis中
https://www.cnblogs.com/adc8868/p/7442306.html

 

scrapy-redis分布式爬虫的搭建过程:https://blog.csdn.net/zwq912318834/article/details/78854571

Scrapy第三篇(基于Scrapy-Redis的分布式以及cookies池):https://cuiqingcai.com/4048.html

 

 

scrapy 下载中间件用法:https://www.cnblogs.com/zhaof/p/7198407.html

scrapy 设置代理:使用 IP 代理池            middleware设置proxy代理           

关于 scrapy 重定向: 禁止重定向的解决方法:https://www.zhaokeli.com/article/8046.html

https://blog.csdn.net/amaomao123/article/details/52511882

 

内容都是从官方文档整理过来的,只整理一部分,要想深入了解,可以看官方文档

 

scrapy整体架构图

Scrapy主要组件

1、引擎(Scrapy)用来处理整个系统的数据流处理, 触发事务(框架核心)。
2、调度器(Scheduler):用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址。
3、下载器(Downloader): 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)。
4、爬虫(Spiders): 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面。
5、项目管道(Pipeline): 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
6、下载器中间件(Downloader Middlewares): 位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
7、爬虫中间件(Spider Middlewares): 介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
8、调度中间件(Scheduler Middewares): 介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。

 

表格:

组件功能
引擎(Scrapy)用来处理整个系统的数据流处理, 触发事务(框架核心)
调度器(Scheduler)用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
下载器(Downloader)用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted上的)
爬虫(Spiders)爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
项目管道(Pipeline)负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据
下载器中间件(Downloader Middlewares)位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应
爬虫中间件(Spider Middlewares)介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出
调度中间件(Scheduler Middewares)介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应

 

Scrapy 框架 的 运行流程:

  • 首先,引擎 从 调度器 中 取出一个链接(URL) 用于 接下来的抓取
  • 引擎 把 URL封装成一个 请求(Request) 传给下载器
  • 下载器 把 资源下载下来,并 封装成 应答包(Response)
  • 爬虫(指自己写的爬虫程序Spider) 解析 应答包(Response)
  • 如果 爬虫 从 Response 中 解析出的是实体(Item),则把 Item(实体) 交给 管道 进行进一步的处理。
  • 如果 爬虫 从 Response 中 解析出的是链接(URL),则把 URL 交给 Scheduler 等待抓取

 

scrapy 框架 中 的 spider 爬取流程

对 spider 来说,爬取的循环类似下文:

  1. 以初始的URL初始化Request,并设置回调函数。 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。

    spider中初始的request是通过调用 start_requests() 来获取的。 start_requests() 读取 start_urls 中的URL, 并以 parse 为回调函数生成 Request 。

  2. 在回调函数内分析返回的(网页)内容,返回 Item 对象、dict、 Request 或者一个包括三者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。

  3. 在回调函数内,您可以使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。

  4. 最后,由spider返回的item将被存到数据库(由某些 Item Pipeline 处理)或使用 Feed exports 存入到文件中。

虽然该循环对任何类型的spider都(多少)适用,但Scrapy仍然为了不同的需求提供了多种默认spider。 

可以查看官方文档了解更多关于不同需求的spider。

 

 

 

初窥Scrapy

 

        Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。其最初是为了 网络抓取 所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

 

一窥示例spider       

为了让您了解Scrapy提供了什么功能,我们将提供一个Scrapy Spider的示例,并且以最简单的方式启动该spider。以下的代码将跟进StackOverflow上具有投票数最多的链接,并且爬取其中的一些数据:

import scrapyclass StackOverflowSpider(scrapy.Spider):name = 'stackoverflow'start_urls = ['http://stackoverflow.com/questions?sort=votes']def parse(self, response):for href in response.css('.question-summary h3 a::attr(href)'):full_url = response.urljoin(href.extract())yield scrapy.Request(full_url, callback=self.parse_question)def parse_question(self, response):yield {'title': response.css('h1 a::text').extract()[0],'votes': response.css('.question .vote-count-post::text').extract()[0],'body': response.css('.question .post-text').extract()[0],'tags': response.css('.question .post-tag::text').extract(),'link': response.url,}

将上述代码存入到某个文件中,以类似于 stackoverflow_spider.py 命名, 并且使用 runspider 命令运行:

scrapy runspider stackoverflow_spider.py -o top-stackoverflow-questions.json

当命令执行完后,您将会得到 top-stackoverflow-questions.json 文件。 该文件以JSON格式保存了StackOverflow上获得upvote最多的问题, 包含了标题、链接、upvote的数目、相关的tags以及以HTML格式保存的问题内容, 看起来类似于这样(为了更容易阅读,对内容进行重新排版):

[{"body": "... LONG HTML HERE ...","link": "http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array","tags": ["java", "c++", "performance", "optimization"],"title": "Why is processing a sorted array faster than an unsorted array?","votes": "9924"
},
{"body": "... LONG HTML HERE ...","link": "http://stackoverflow.com/questions/1260748/how-do-i-remove-a-git-submodule","tags": ["git", "git-submodules"],"title": "How do I remove a Git submodule?","votes": "1764"
},
...]

Here’s the code for a spider that scrapes famous quotes from website http://quotes.toscrape.com, following the pagination:

import scrapyclass QuotesSpider(scrapy.Spider):name = "quotes"start_urls = ['http://quotes.toscrape.com/tag/humor/',]def parse(self, response):for quote in response.css('div.quote'):yield {'text': quote.css('span.text::text').extract_first(),'author': quote.xpath('span/small/text()').extract_first(),}next_page = response.css('li.next a::attr("href")').extract_first()if next_page is not None:next_page = response.urljoin(next_page)yield scrapy.Request(next_page, callback=self.parse)

将上述代码存入到某个文件中,以类似于 quotes_spider.py 命名, 并且使用 runspider 命令运行:

scrapy runspider quotes_spider.py -o quotes.json

 

刚刚发生了什么?

当您运行 scrapy runspider somefile.py 命令时,Scrapy尝试从该文件中查找Spider的定义,并且在爬取引擎中运行它。

Scrapy首先读取定义在 start_urls 属性中的URL(在本示例中,就是StackOverflow的top question页面的URL), 创建请求,并且将接收到的response作为参数调用默认的回调函数 parse ,来启动爬取。 在回调函数 parse 中,我们使用CSS Selector来提取链接。接着,我们产生(yield)更多的请求, 注册 parse_question 作为这些请求完成时的回调函数。

这里,您可以注意到Scrapy的一个最主要的优势: 请求(request)是 被异步调度和处理的 。 这意味着,Scrapy并不需要等待一个请求(request)完成及处理,在此同时, 也发送其他请求或者做些其他事情。 这也意味着,当有些请求失败或者处理过程中出现错误时,其他的请求也能继续处理。

在允许您可以以非常快的速度进行爬取时(以容忍错误的方式同时发送多个request), Scrapy也通过 一些设置 来允许您控制其爬取的方式。 例如,您可以为两个request之间设置下载延迟, 限制单域名(domain)或单个IP的并发请求量,甚至可以 使用自动限制插件 来自动处理这些问题。

最终, parse_question 回调函数从每个页面中爬取到问题(question)的数据并产生了一个dict, Scrapy收集并按照终端(command line)的要求将这些结果写入到了JSON文件中。

 

注解

这里使用了 feed exports 来创建了JSON文件, 您可以很容易的改变导出的格式(比如XML或CSV)或者存储后端(例如FTP或者 Amazon S3)。 您也可以编写 item pipeline 来将item存储到数据库中。

 

还有什么?

您已经了解了如何通过Scrapy提取存储网页中的信息,但这仅仅只是冰山一角。Scrapy提供了很多强大的特性来使得爬取更为简单高效, 例如:

  • 对HTML, XML源数据 选择及提取 的内置支持, 提供了CSS选择器(selector)以及XPath表达式进行处理, 以及一些帮助函数(helper method)来使用正则表达式来提取数据.
  • 提供 交互式shell终端 , 为您测试CSS及XPath表达式,编写和调试爬虫提供了极大的方便
  • 通过 feed导出 提供了多格式(JSON、CSV、XML),多存储后端(FTP、S3、本地文件系统)的内置支持
  • 提供了一系列在spider之间共享的可复用的过滤器(即 Item Loaders),对智能处理爬取数据提供了内置支持。
  • 针对非英语语系中不标准或者错误的编码声明, 提供了自动检测以及健壮的编码支持。
  • 高扩展性。您可以通过使用 signals ,设计好的API(中间件, extensions, pipelines)来定制实现您的功能。
  • 内置的中间件及扩展为下列功能提供了支持: * cookies and session 处理 * HTTP 压缩 * HTTP 认证 * HTTP 缓存 * user-agent模拟 * robots.txt * 爬取深度限制 * 其他
  • 内置 Telnet终端 ,通过在Scrapy进程中钩入Python终端,使您可以查看并且调试爬虫
  • 以及其他一些特性,例如可重用的,从 Sitemaps 及 XML/CSV feeds中爬取网站的爬虫、 可以 自动下载 爬取到的数据中的图片(或者其他资源)的media pipeline、 带缓存的DNS解析器,以及更多的特性。

 

 

安装指南

 

安装Scrapy

官网英文版安装向导       官网中文版安装向导

 

基本使用

 

基本命令

1. scrapy startproject 项目名称- 在当前目录中创建中创建一个项目文件(类似于Django)2. scrapy genspider [-t template] <name> <domain>- 创建爬虫应用如:scrapy gensipider  oldboy oldboy.comscrapy gensipider -t xmlfeed autohome autohome.com.cnPS:查看所有命令:scrapy gensipider -l查看模板命令:scrapy gensipider -d 模板名称3. scrapy list- 展示爬虫应用列表4. scrapy crawl 爬虫应用名称- 运行单独爬虫应用

项目结构以及爬虫应用简介

project_name/scrapy.cfgproject_name/__init__.pyitems.pypipelines.pysettings.pyspiders/__init__.py爬虫1.py爬虫2.py爬虫3.py

文件说明:

  • scrapy.cfg  项目的主配置信息。(真正爬虫相关的配置信息在settings.py文件中)
  • items.py    设置数据存储模板,用于结构化数据,如:Django的Model
  • pipelines    数据处理行为,如:一般结构化的数据持久化
  • settings.py 配置文件,如:递归的层数、并发数,延迟下载等
  • spiders      爬虫目录,如:创建文件,编写爬虫规则

爬虫1.py

import scrapyclass XiaoHuarSpider(scrapy.spiders.Spider):name = "xiaohuar"                            # 爬虫名称 *****allowed_domains = ["xiaohuar.com"]  # 允许的域名start_urls = ["http://www.xiaohuar.com/hua/",   # 其实URL]def parse(self, response):# 访问起始URL并获取结果后的回调函数# windows编码问题在头部添加下面两句
import sys,os
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')

 

 

Scrapy入门教程

 

在本篇教程中,我们假定您已经安装好Scrapy。

本篇教程中将带您完成下列任务:

  1. 创建一个Scrapy项目
  2. 定义提取的Item
  3. 编写爬取网站的 spider 并提取 Item
  4. 编写 Item Pipeline 来存储提取到的Item(即数据)

Scrapy由 Python 编写。如果您刚接触并且好奇这门语言的特性以及Scrapy的详情, 对于已经熟悉其他语言并且想快速学习Python的编程老手, 我们推荐 Learn Python The Hard Way 、 Dive Into Python 3,或者 跟随  Python Tutorial。 对于想从Python开始学习的编程新手, 非程序员的Python学习资料列表 将是您的选择。

 

创建项目

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

scrapy startproject tutorial

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

tutorial/scrapy.cfgtutorial/__init__.pyitems.pypipelines.pysettings.pyspiders/__init__.py...

 

创建项目与配置环境后各部分组件:

 

 

定义Item

Item 是保存爬取到的数据的容器;其使用方法和python字典类似。虽然您也可以在Scrapy中直接使用dict,但是 Item 提供了额外保护机制来避免拼写错误导致的未定义字段错误。 They can also be used with Item Loaders, a mechanism with helpers to conveniently populate Items.

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

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

import scrapyclass DmozItem(scrapy.Item):title = scrapy.Field()link = scrapy.Field()desc = scrapy.Field()

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

 

 

编写第一个爬虫(Spider)

Spider是用户编写用于从单个网站(或者一些网站)爬取数据的类。其包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容, 提取生成 item 的方法。为了创建一个Spider,您必须继承 scrapy.Spider 类, 且定义一些属性:

  • name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。
  • start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
  • start_requests(): must return an iterable of Requests (you can return a list of requests or write a generator function) which the Spider will begin to crawl from. Subsequent requests will be generated successively from these initial requests.
  • parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。

以下为我们的第一个Spider代码,保存在 tutorial/spiders 目录下的 dmoz_spider.py 文件中:

使用 startu_urls 示例:

import scrapyclass DmozSpider(scrapy.Spider):name = "dmoz"allowed_domains = ["dmoz.org"]start_urls = ["http://www.dmoz.org/Computers/Programming/Languages/Python/Books/","http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"]def parse(self, response):filename = response.url.split("/")[-2] + '.html'with open(filename, 'wb') as f:f.write(response.body)

第二个Spider代码,保存在 tutorial/spiders 目录下的 quotes_spider.py 文件中:

使用 start_requests 函数 示例:

import scrapyclass QuotesSpider(scrapy.Spider):name = "quotes"def start_requests(self):urls = ['http://quotes.toscrape.com/page/1/','http://quotes.toscrape.com/page/2/',]for url in urls:yield scrapy.Request(url=url, callback=self.parse)def parse(self, response):page = response.url.split("/")[-2]filename = 'quotes-%s.html' % pagewith open(filename, 'wb') as f:f.write(response.body)self.log('Saved file %s' % filename)

 

关闭 Scrapy 的 robot.txt 功能

关闭 scrapy 自带的 ROBOTSTXT_OBEY 功能,在setting找到这个变量,设置为False。

   

 

 

运行程序并爬取数据

进入项目的根目录,执行下列命令启动spider:

scrapy crawl dmoz
或者
scrapy crawl quotes

在 项目 的 根目录 下 多了两个HTML文件

继续在项目的根目录下运行 :scrapy crawl dmoz

 

刚才发生了什么?

Scrapy 通过 start_requests 方法调度 scrapy.Request 对象,然后根据 request 关联的 回调 函数,把每一个接收到response传给回调函数处理

一个快捷的处理

Instead of implementing a start_requests() method that generates scrapy.Request objects from URLs, you can just define a start_urls class attribute with a list of URLs. This list will then be used by the default implementation of start_requests() to create the initial requests for your spider:

import scrapyclass QuotesSpider(scrapy.Spider):name = "quotes"start_urls = ['http://quotes.toscrape.com/page/1/','http://quotes.toscrape.com/page/2/',]def parse(self, response):page = response.url.split("/")[-2]filename = 'quotes-%s.html' % pagewith open(filename, 'wb') as f:f.write(response.body)

The parse() method will be called to handle each of the requests for those URLs, even though we haven’t explicitly told Scrapy to do so. This happens because parse() is Scrapy’s default callback method, which is called for requests without an explicitly assigned callback.

 

提取Item

Selectors选择器简介

从网页中提取数据有很多方法。Scrapy使用了一种基于 XPath 和 CSS 表达式机制: Scrapy Selectors。  关于selector和其他提取机制的信息请参考 Selector文档 。

这里给出XPath表达式的例子及对应的含义:

  • /html/head/title: 选择HTML文档中 <head> 标签内的 <title> 元素
  • /html/head/title/text(): 选择上面提到的 <title> 元素的文字
  • //td: 选择所有的 <td> 元素
  • //div[@class="mine"]: 选择所有具有 class="mine" 属性的 div 元素

上边仅仅是几个简单的XPath例子,XPath实际上要比这远远强大的多。 如果您想了解的更多,我们推荐 通过这些例子来学习XPath, 以及 这篇教程学习”how to think in XPath”.

CSS vs XPath: 您可以仅仅使用CSS Selector来从网页中 提取数据。不过, XPath提供了更强大的功能。其不仅仅能指明数据所在的路径, 还能查看数据: 比如,您可以这么进行选择: 包含文字 ‘Next Page’ 的链接 。 正因为如此,即使您已经了解如何使用 CSS selector, 我们仍推荐您使用XPath

为了配合CSS与XPath,Scrapy除了提供了 Selector 之外,还提供了方法来避免每次从response中提取数据时生成selector的麻烦。Selector有四个基本的方法(点击相应的方法可以看到详细的API文档):

  • xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表 。
  • css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表.
  • extract(): 序列化该节点为unicode字符串并返回list。
  • re(): 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。

  

在Shell中尝试Selector选择器

为了介绍Selector的使用方法,接下来我们将要使用内置的 Scrapy shell 。Scrapy Shell需要您预装好 IPython (一个扩展的Python终端)。您需要进入项目的根目录,执行下列命令来启动shell:

scrapy shell "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/"
或者
scrapy shell "http://quotes.toscrape.com/page/1/"

当您在终端运行Scrapy时,请一定记得给url地址加上引号,否则包含参数的url(例如 & 字符)会导致Scrapy运行失败。

当shell载入后,您将得到一个包含response数据的本地 response 变量。输入 response.body 将输出response的包体, 输出 response.headers 可以看到response的包头。

#TODO.. 更为重要的是, response 拥有一个 selector 属性, 该属性是以该特定 response 初始化的类 Selector 的对象。 您可以通过使用 response.selector.xpath() 或 response.selector.css() 来对 response 进行查询。 此外,scrapy也对 response.selector.xpath() 及 response.selector.css() 提供了一些快捷方式, 例如 response.xpath() 或 response.css() ,

同时,shell根据response提前初始化了变量 sel 。该selector根据response的类型自动选择最合适的分析规则(XML vs HTML)。

In [1]: response.xpath('//title')
Out[1]: [<Selector xpath='//title' data=u'<title>Open Directory - Computers: Progr'>]In [2]: response.xpath('//title').extract()
Out[2]: [u'<title>Open Directory - Computers: Programming: Languages: Python: Books</title>']In [3]: response.xpath('//title/text()')
Out[3]: [<Selector xpath='//title/text()' data=u'Open Directory - Computers: Programming:'>]In [4]: response.xpath('//title/text()').extract()
Out[4]: [u'Open Directory - Computers: Programming: Languages: Python: Books']In [5]: response.xpath('//title/text()').re('(\w+):')
Out[5]: [u'Computers', u'Programming', u'Languages', u'Python']
response.css('title')
response.css('title::text').extract()
response.css('title').extract()
response.css('title::text').extract_first()
response.css('title::text')[0].extract()
response.css('title::text').re(r'Quotes.*')
response.css('title::text').re(r'Q\w+')
response.css('title::text').re(r'(\w+) to (\w+)')

之前提到过,每个 .xpath() 调用返回selector组成的list,因此我们可以拼接更多的 .xpath() 来进一步获取某个节点。我们将在下边使用这样的特性:

for sel in response.xpath('//ul/li'):title = sel.xpath('a/text()').extract()link = sel.xpath('a/@href').extract()desc = sel.xpath('text()').extract()print title, link, desc

关于嵌套selctor的更多详细信息,请参考 嵌套选择器(selectors) 以及 选择器(Selectors) 文档中的 使用相对XPaths 部分。

在我们的spider中加入这段代码:

import scrapyclass DmozSpider(scrapy.Spider):name = "dmoz"allowed_domains = ["dmoz.org"]start_urls = ["http://www.dmoz.org/Computers/Programming/Languages/Python/Books/","http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"]def parse(self, response):for sel in response.xpath('//ul/li'):title = sel.xpath('a/text()').extract()link = sel.xpath('a/@href').extract()desc = sel.xpath('text()').extract()print title, link, desc

 

使用item

Item 对象是自定义的python字典。 您可以使用标准的字典语法来获取到其每个字段的值。(字段即是我们之前用Field赋值的属性):

>>> item = DmozItem()
>>> item['title'] = 'Example title'
>>> item['title']
'Example title'

为了将爬取的数据返回,我们最终的代码将是:

import scrapyfrom tutorial.items import DmozItemclass DmozSpider(scrapy.Spider):name = "dmoz"allowed_domains = ["dmoz.org"]start_urls = ["http://www.dmoz.org/Computers/Programming/Languages/Python/Books/","http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"]def parse(self, response):for sel in response.xpath('//ul/li'):item = DmozItem()item['title'] = sel.xpath('a/text()').extract()item['link'] = sel.xpath('a/@href').extract()item['desc'] = sel.xpath('text()').extract()yield item

您可以在 dirbot 项目中找到一个具有完整功能的spider。该项目可以通过 https://github.com/scrapy/dirbot 找到。

现在对dmoz.org进行爬取将会产生 DmozItem 对象:

 

提取数据

import scrapyclass QuotesSpider(scrapy.Spider):name = "quotes"start_urls = ['http://quotes.toscrape.com/page/1/','http://quotes.toscrape.com/page/2/',]def parse(self, response):for quote in response.css('div.quote'):yield {'text': quote.css('span.text::text').extract_first(),'author': quote.css('small.author::text').extract_first(),'tags': quote.css('div.tags a.tag::text').extract(),}

If you run this spider, it will output the extracted data with the log:

2016-09-19 18:57:19 [scrapy.core.scraper] DEBUG: Scraped from <200 http://quotes.toscrape.com/page/1/>
{'tags': ['life', 'love'], 'author': 'André Gide', 'text': '“It is better to be hated for what you are than to be loved for what you are not.”'}
2016-09-19 18:57:19 [scrapy.core.scraper] DEBUG: Scraped from <200 http://quotes.toscrape.com/page/1/>
{'tags': ['edison', 'failure', 'inspirational', 'paraphrased'], 'author': 'Thomas A. Edison', 'text': "“I have not failed. I've just found 10,000 ways that won't work.”"}

  

存储数据

最简单的是通过命令行:scrapy crawl quotes -o quotes.json

该命令将采用 JSON 格式对爬取的数据进行序列化,生成 quotes.json 文件

在类似本篇教程里这样小规模的项目中,这种存储方式已经足够。 如果需要对爬取到的item做更多更为复杂的操作,您可以编写 Item Pipeline 。 类似于我们在创建项目时对Item做的,用于您编写自己的 tutorial/pipelines.py 也被创建。 不过如果您仅仅想要保存item,您不需要实现任何的pipeline。

 

 

追踪链接(Following links)

 

既然已经能从页面上爬取数据了,为什么不提取您感兴趣的页面的链接,追踪他们, 读取这些链接的数据呢?

下面是实现这个功能的改进版spider:

import scrapyfrom tutorial.items import DmozItemclass DmozSpider(scrapy.Spider):name = "dmoz"allowed_domains = ["dmoz.org"]start_urls = ["http://www.dmoz.org/Computers/Programming/Languages/Python/",]def parse(self, response):for href in response.css("ul.directory.dir-col > li > a::attr('href')"):url = response.urljoin(response.url, href.extract())yield scrapy.Request(url, callback=self.parse_dir_contents)def parse_dir_contents(self, response):for sel in response.xpath('//ul/li'):item = DmozItem()item['title'] = sel.xpath('a/text()').extract()item['link'] = sel.xpath('a/@href').extract()item['desc'] = sel.xpath('text()').extract()yield item

现在, parse() 仅仅从页面中提取我们感兴趣的链接,使用 response.urljoin 方法构造一个绝对路径的URL(页面上的链接都是相对路径的), 产生(yield)一个请求, 该请求使用 parse_dir_contents() 方法作为回调函数, 用于最终产生我们想要的数据.。

这里展现的即是Scrpay的追踪链接的机制: 当您在回调函数中yield一个Request后, Scrpay将会调度,发送该请求,并且在该请求完成时,调用所注册的回调函数。

基于此方法,您可以根据您所定义的跟进链接的规则,创建复杂的crawler,并且, 根据所访问的页面,提取不同的数据.

一种常见的方法是,回调函数负责提取一些item,查找能跟进的页面的链接, 并且使用相同的回调函数yield一个 Request:

def parse_articles_follow_next_page(self, response):for article in response.xpath("//article"):item = ArticleItem()... extract article data hereyield itemnext_page = response.css("ul.navigation > li.next-page > a::attr('href')")if next_page:url = response.urljoin(next_page[0].extract())yield scrapy.Request(url, self.parse_articles_follow_next_page)

上述代码将创建一个循环,跟进所有下一页的链接,直到找不到为止 – 对于爬取博客、论坛以及其他做了分页的网站十分有效

另一种常见的需求是从多个页面构建item的数据, 这可以使用 在回调函数中传递信息的技巧.

 

注解

上述代码仅仅作为阐述scrapy机制的样例spider, 想了解 如何实现一个拥有小型的规则引擎(rule engine)的通用spider 来构建您的crawler, 请查看 CrawlSpider

import scrapyclass QuotesSpider(scrapy.Spider):name = "quotes"start_urls = ['http://quotes.toscrape.com/page/1/',]def parse(self, response):for quote in response.css('div.quote'):yield {'text': quote.css('span.text::text').extract_first(),'author': quote.css('small.author::text').extract_first(),'tags': quote.css('div.tags a.tag::text').extract(),}next_page = response.css('li.next a::attr(href)').extract_first()if next_page is not None:next_page = response.urljoin(next_page)yield scrapy.Request(next_page, callback=self.parse)
import scrapyclass AuthorSpider(scrapy.Spider):name = 'author'start_urls = ['http://quotes.toscrape.com/']def parse(self, response):# follow links to author pagesfor href in response.css('.author + a::attr(href)').extract():yield scrapy.Request(response.urljoin(href),callback=self.parse_author)# follow pagination linksnext_page = response.css('li.next a::attr(href)').extract_first()if next_page is not None:next_page = response.urljoin(next_page)yield scrapy.Request(next_page, callback=self.parse)def parse_author(self, response):def extract_with_css(query):return response.css(query).extract_first().strip()yield {'name': extract_with_css('h3.author-title::text'),'birthdate': extract_with_css('.author-born-date::text'),'bio': extract_with_css('.author-description::text'),}

 

 

使用Spider参数

 

当运行爬虫时,可以使用 -a 选项,为爬虫提供命令行参数:

scrapy crawl quotes -o quotes-humor.json -a tag=humor

设置的参数通过 Spider 的 __init__ 方法 来变成 的 spider attributes.

这个例子中, 提供给 tag 参数的值 可以通过 self.tag 调用。

import scrapyclass QuotesSpider(scrapy.Spider):name = "quotes"def start_requests(self):url = 'http://quotes.toscrape.com/'tag = getattr(self, 'tag', None)if tag is not None:url = url + 'tag/' + tagyield scrapy.Request(url, self.parse)def parse(self, response):for quote in response.css('div.quote'):yield {'text': quote.css('span.text::text').extract_first(),'author': quote.css('small.author::text').extract_first(),}next_page = response.css('li.next a::attr(href)').extract_first()if next_page is not None:next_page = response.urljoin(next_page)yield scrapy.Request(next_page, self.parse)

如果传递 tag=humor 参数给 spider,就只会访问url的 “humor” 标签, such as http://quotes.toscrape.com/tag/humor.

更过关于处理spider参数:https://doc.scrapy.org/en/1.3/topics/spiders.html#spiderargs

 

 

例  子

 

学习的最好方法就是参考例子,Scrapy也不例外。Scrapy提供了一个叫做 dirbot 的样例项目供您把玩学习。其包含了在教程中介绍的dmoz spider。您可以通过 https://github.com/scrapy/dirbot 找到 dirbot 。README文件对项目内容进行了详细的介绍。

Scrapy project 另一个名叫 quotesbot 的样例项目, 包含两个 spiders 关于 http://quotes.toscrape.com, 一个是使用 CSS selectors 另一个是使用 XPath expressions.

中间件模板:

# -*- coding: utf-8 -*-# Define here the models for your spider middleware
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/spider-middleware.htmlfrom scrapy import signalsclass SpidercoreSpiderMiddleware(object):# Not all methods need to be defined. If a method is not defined,# scrapy acts as if the spider middleware does not modify the# passed objects.@classmethoddef from_crawler(cls, crawler):# This method is used by Scrapy to create your spiders.s = cls()crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)return sdef process_spider_input(self, response, spider):# Called for each response that goes through the spider# middleware and into the spider.# Should return None or raise an exception.return Nonedef process_spider_output(self, response, result, spider):# Called with the results returned from the Spider, after# it has processed the response.# Must return an iterable of Request, dict or Item objects.for i in result:yield idef process_spider_exception(self, response, exception, spider):# Called when a spider or process_spider_input() method# (from other spider middleware) raises an exception.# Should return either None or an iterable of Response, dict# or Item objects.passdef process_start_requests(self, start_requests, spider):# Called with the start requests of the spider, and works# similarly to the process_spider_output() method, except# that it doesn’t have a response associated.# Must return only requests (not items).for r in start_requests:yield rdef spider_opened(self, spider):spider.logger.info('Spider opened: %s' % spider.name)class SpidercoreDownloaderMiddleware(object):# Not all methods need to be defined. If a method is not defined,# scrapy acts as if the downloader middleware does not modify the# passed objects.@classmethoddef from_crawler(cls, crawler):# This method is used by Scrapy to create your spiders.s = cls()crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)return sdef process_request(self, request, spider):# Called for each request that goes through the downloader# middleware.# Must either:# - return None: continue processing this request# - or return a Response object# - or return a Request object# - or raise IgnoreRequest: process_exception() methods of#   installed downloader middleware will be calledreturn Nonedef process_response(self, request, response, spider):# Called with the response returned from the downloader.# Must either;# - return a Response object# - return a Request object# - or raise IgnoreRequestreturn responsedef process_exception(self, request, exception, spider):# Called when a download handler or a process_request()# (from other downloader middleware) raises an exception.# Must either:# - return None: continue processing this exception# - return a Response object: stops process_exception() chain# - return a Request object: stops process_exception() chainpassdef spider_opened(self, spider):spider.logger.info('Spider opened: %s' % spider.name)

用户代理(User-Agent)中间件 示例代码:

# coding: utf-8import random
from scrapy.downloadermiddlewares.useragent import UserAgentMiddlewareclass RandomUserAgentMiddleware(UserAgentMiddleware):agents = ["Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)""Chrome/67.0.3396.62 Safari/537.36","User-Agent,Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)""Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240"]def __init__(self, user_agent=''):super(RandomUserAgentMiddleware, self).__init__()self.user_agent = user_agentdef _user_agent(self, spider):if hasattr(spider, 'user_agent'):return spider.user_agentelif self.user_agent:return self.user_agentreturn random.choice(self.agents)def process_request(self, request, spider):ua = self._user_agent(spider)if ua:request.headers.setdefault('User-Agent', ua)

然后把中间件加到 ITEM_PIPELINE 设置里面即可 

 

 

在 Pycharm 中调试 scrapy 爬虫的两种方法

 

通常,运行scrapy爬虫的方式是在命令行输入scrapy crawl <spider_name>,调试的常用方式是在命令行输入scrapy shell <url_name>。总的来说,调试方法比较单一。其实,还有两种调试方法,可以在pycharm中实现调试。

 

1.使用scrapy.cmdline的execute方法

首先,在项目文件 scrapy.cfg 的同级建立 main.py 文件(注意,必须是同级建立),在其中键入如下代码:

from scrapy import cmdline 
import sys
import ossys.path.append(os.path.dirname(os.path.abspath(__file__)))cmdline.execute(['scrapy', 'crawl', 'spider_name'])  # 你需要将此处的spider_name替换为你自己的爬虫名称# 或者 cmdline.execute('scrapy crawl spider_name'.split(' '))pass

在其余爬虫文件中设置断点后,运行main.py,即可实现在pycharm中的调试。

 

2.使用scrapy的CrawlerProcess方法

在项目文件scrapy.cfg的同级建立main.py文件(注意,必须是同级建立),在其中键入如下代码:

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settingsif __name__ == '__main__':process = CrawlerProcess(get_project_settings())process.crawl('spider_name')    #  你需要将此处的spider_name替换为你自己的爬虫名称process.start()

在其余爬虫文件中设置断点后,运行main.py,即可实现在pycharm中的调试。

两种方式都很简单实用,值得掌握。

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/496617.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧停车产业链市场全透析

来源&#xff1a;慧天地最近&#xff0c;Goodwin调查发现&#xff0c;在城市地区&#xff0c;接近30%的交通拥堵源自于司机寻找停车位。据称&#xff0c;到2020年&#xff0c;将会有20亿的汽车在公路上跑着&#xff0c;这就意味着&#xff0c;届时汽车的数量将比目前多了7.7亿辆…

语音合成与识别技术在C#中的应用 (转 )

语音合成与识别技术在C#中的应用 (转 &#xff09; 我们要想实现中文发音或中文语音识别&#xff0c;必需先安装微软的Speech Application SDK&#xff08;SASDK&#xff09;&#xff0c;它的最新版本是 SAPI 5.1 他能够识别中、日、英三种语言&#xff0c;你可以在这里下载&am…

left join 和join区别_sleep、yield、join方法简介与用法 sleep与wait区别 多线程中篇

Object中的wait、notify、notifyAll&#xff0c;可以用于线程间的通信&#xff0c;核心原理为借助于监视器的入口集与等待集逻辑通过这三个方法完成线程在指定锁&#xff08;监视器&#xff09;上的等待与唤醒&#xff0c;这三个方法是以锁&#xff08;监视器&#xff09;为中心…

深度干货!值得精读的2018自动驾驶行业发展报告

来源&#xff1a; 机器人大讲堂摘要随着科技革命的深入推进&#xff0c;人类社会进入万物互联、万物智能的智能化新时代。自动驾驶技术在人工智能和汽车行业的飞速发展下逐渐成为业界焦点。自动驾驶技术是汽车产业与高性能计算芯片、人工智能、物联网等新一代信息技术深度融合的…

TCP 连接状态

TCP十一种状态 全部11种状态 1. 客户端独有的&#xff1a;&#xff08;1&#xff09;SYN_SENT &#xff08;2&#xff09;FIN_WAIT1 &#xff08;3&#xff09;FIN_WAIT2 &#xff08;4&#xff09;CLOSING &#xff08;5&#xff09;TIME_WAIT 。 2. 服务器独有的&#xff1a…

Java加密与解密的艺术~MD算法实现

MD系列算法的实现是通过MessageDigest类来完成的&#xff0c;如果需要以流的处理方式完成消息摘要&#xff0c;则需要使用DigestInputStream和DigestOutputStream。 MD4 package org.zlex.chapter06_1_2;import java.security.MessageDigest; import java.security.Security;i…

密码学知识

文章目录密码学一、对称加密体系二、模式三、非对称加密体系四、数据完整性五、数字签名六、国密算法七、SSL协议八、CA密码学 提示&#xff1a;本文包括常见的对称加密和非对称加密算法&#xff0c;hash&#xff0c;数字签名 提示&#xff1a;以下是本篇文章正文内容&#xf…

德勒报告:2018年全球生命科学发展趋势

来源&#xff1a;新浪医药、战略前沿技术健康生命科学&#xff08;Health life sciences&#xff09;是指应用生物学和技术来促进健康护理&#xff0c;包括制药、医疗技术、基因组学、诊断学、数字医疗等等。这一板块产品种类繁多&#xff0c;包括药品、医疗技术、诊断和数字工…

Uber致人死亡或为自动驾驶肇事责任 没有判例可循

图&#xff1a;Uber自动驾驶测试车辆引发致人死亡交通事故凤凰网科技讯 据《福布斯》网站北京时间3月20日报道&#xff0c;美国当地时间本周日傍晚&#xff0c;一辆由Uber运营的自动驾驶汽车在亚利桑那州坦佩(Tempe)撞倒了一名女性并致其死亡。Uber周一表示&#xff0c;公司暂停…

28个Unix/Linux的命令行神器

From: http://os.51cto.com/art/201207/347414.htm 下面收集的Unix/Linux下的28个命令行下的工具&#xff0c;有一些是大家熟悉的&#xff0c;有一些是非常有用的&#xff0c;有一些是不为人知的。这些工具都非常不错&#xff0c;希望每个人都知道。本篇文章还在Hacker News上被…

Java加密与解密的艺术~SHA算法实现

MesssageDigest类也支持SHA算法&#xff0c;主要包含SHA-1、SHA-256、SHA-384和SHA-512四种算法。通过第三方加密组件包Bouncy Castle&#xff0c;可支持SHA-224算法。 SHA Java原始 /*** 2009-9-3*/ package org.zlex.chapter06_2_1;import java.security.MessageDigest; /**…

linux 无法打开.ttf_win7系统ttf文件打不开怎么办【解决方法】

我们都清楚ttf文件是windows系统当中的字体文件&#xff0c;能够直接通过这个文件进行字体的添加&#xff0c;不过最近有位win7系统用户却遇到了ttf文件无法打开的情况&#xff0c;系统提示“该文件没有与之关联的程序来执行该操作。请安装一个程序&#xff0c;或者&#xff0c…

全球20大智慧城市排行榜揭晓:无锡列中国第一,银川、杭州上榜!

来源&#xff1a;Juniper Research、物联网智库近日&#xff0c;英国市场调研机构Juniper Research发布了“全球智慧城市Top 20”的榜单&#xff0c;这份榜单从出行、医疗、公共安全和工作效率四个方面对城市的智能化程度进行综合评定&#xff0c;并揭示了这些城市在节省时间、…

Mono 2.0

Mono 2.0 Mono 2.0 发布有一段时间了,早就想体验一下,一直没时间,最近比效闲,非常闲,于是就尝试了一下Mono 2.0 操作系统 考虑到兼容问题,我没选择常用的Rad Hat,而是选择了openSUSE 11.0 , openSUSE 11.0 我也是第一次用, 在Virtual PC 2007上安装,每次到开始安装就黑屏,…

Java加密与解密的艺术~MAC算法实现

Java 原生 /*** 2009-9-10*/ package org.zlex.chapter06_3_1;import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec;/*** MAC加密组件* * author 梁栋* version 1.0* since 1.0*/ public abs…

mysql rpm 启动_MySQL安装(rpm)和启动配置

MySQL安装(rpm)和启动配置安装环境&#xff1a;OS&#xff1a;Oracle Linux 5.9安装步骤&#xff1a;1.解压MySql安装包[rootbakdbserver mysql]# tar -xf MySQL-5.5.24-1.rhel5.x86_64.tar[rootbakdbserver mysql]# ll总计 373920-rw-r--r-- 1 root root 191242240 2012-05-2…

量子计算陷入难解困境,未来发展何去何从?

来源&#xff1a;科研圈量子计算机在一些具体任务上的表现很快就能超越传统电子计算机&#xff0c;但是在量子计算真正实现其巨大潜力前&#xff0c;依然需要克服许多基础性的难题。在量子计算的可行性被质疑长达几十年后&#xff0c;全世界范围内忽然掀起了对于量子计算的追逐…

mysql 64位 8.0.11_mysql8.0.11 在windows64安装 步骤

环境&#xff1a;Windows 101一、安装1. 解压zip包到安装目录比如我的安装目录是&#xff1a;D:\Program\MySQL2.配置文件在Windows系统中&#xff0c;配置文件默认是安装目录下的 my.ini 文件&#xff0c;部分配置需要在初始安装时配置&#xff0c;大部分也可以在安装完成后进…

ProxyChains

proxychains-ng&#xff1a;https://github.com/rofl0r/proxychains-ng proxychains&#xff1a;https://github.com/haad/proxychains shadowsocks&#xff1a;https://github.com/shadowsocks/shadowsocks 安装了 shadowsocks 之后&#xff0c;只能网页出去逛逛&#xff0c;…

IDC发布对话式人工智能白皮书|附下载

来源&#xff1a;专知丨公众号近日&#xff0c;全球著名的信息技术、电信行业和消费科技咨询公司IDC&#xff08;国际数据公司&#xff0c; International Data Corporation&#xff09;发布了《对话式人工智能白皮书》&#xff08;下文简称《白皮书》&#xff09;。《白皮书》…