Python网络爬虫2 ---- scrapy爬虫架构介绍和初试

本文涉及的产品
.cn 域名,1个 12个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 原文出处:http://my.oschina.net/dragonblog/blog/173290 上一篇文章的环境搭建是相对于手动操作的过程,而大家可能对这个疑问是什么是scrapy?为什么要用scrapy?下面主要是对这两个问题的简要回答。

原文出处:http://my.oschina.net/dragonblog/blog/173290


上一篇文章的环境搭建是相对于手动操作的过程,而大家可能对这个疑问是什么是scrapy?为什么要用scrapy?下面主要是对这两个问题的简要回答。

请尊重作者的工作,转载请注明出处http://my.oschina.net/dragonblog/blog/173545

相信大家在百度或google上一搜索scrapy都能够找到一大堆的结果,由于我本人对scrapy没有太了解,因此这里我也是引用了网络上的说法对scrapy进行说明,也希望各位能够多指点一下小弟。

========================华丽的分割线========================

Scrapy 是一套基于Twisted的异步处理框架,是纯python实现的爬虫框架,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容或者各种图片。下图显示了Scrapy的大体架构,其中包含了scheduler、item pipeline、downloader、spider以及engine这几个组件模块,而其中的绿色箭头则说明了整套系统的数据处理流程。


下面就来一个个解释每个组件的作用及数据的处理过程。

一、组件说明:

    1、Scrapy Engine(Scrapy引擎)

    Scrapy引擎是用来控制整个系统的数据处理流程,并进行事务处理的触发。更多的详细内容可以看下面的数据处理流程。

    2、Scheduler(调度)

    调度程序从Scrapy引擎接受请求并排序列入队列,并在Scrapy引擎发出请求后返还给他们。

    3、Downloader(下载器)

    下载器的主要职责是抓取网页并将网页内容返还给蜘蛛( Spiders)。

    4、Spiders(蜘蛛)

    蜘蛛是有Scrapy用户自己定义用来解析网页并抓取制定URL返回的内容的类,每个蜘蛛都能处理一个域名或一组域名。换句话说就是用来定义特定网站的抓取和解析规则。

    蜘蛛的整个抓取流程(周期)是这样的:

    (1)首先获取第一个URL的初始请求,当请求返回后调取一个回调函数。第一个请求是通过调用start_requests()方法。该方法默认从start_urls中的Url中生成请求,并执行解析来调用回调函数。

    (2)在回调函数中,你可以解析网页响应并返回项目对象和请求对象或两者的迭代。这些请求也将包含一个回调,然后被Scrapy下载,然后有指定的回调处理。

    (3)在回调函数中,你解析网站的内容,同程使用的是Xpath选择器(但是你也可以使用BeautifuSoup, lxml或其他任何你喜欢的程序),并生成解析的数据项。

    (4)最后,从蜘蛛返回的项目通常会进驻到项目管道。

5、Item Pipeline(项目管道)

    项目管道的主要责任是负责处理有蜘蛛从网页中抽取的项目,他的主要任务是清晰、验证和存储数据。当页面被蜘蛛解析后,将被发送到项目管道,并经过几个特定的次序处理数据。每个项目管道的组件都是有一个简单的方法组成的Python类。他们获取了项目并执行他们的方法,同时他们还需要确定的是是否需要在项目管道中继续执行下一步或是直接丢弃掉不处理。

项目管道通常执行的过程有:

  1. 清洗HTML数据
  2. 验证解析到的数据(检查项目是否包含必要的字段)
  3. 检查是否是重复数据(如果重复就删除)
  4. 将解析到的数据存储到数据库中

6、Downloader middlewares(下载器中间件)

    下载中间件是位于Scrapy引擎和下载器之间的钩子框架,主要是处理Scrapy引擎与下载器之间的请求及响应。它提供了一个自定义的代码的方式来拓展 Scrapy的功能。下载中间器是一个处理请求和响应的钩子框架。他是轻量级的,对Scrapy尽享全局控制的底层的系统。

7、Spider middlewares(蜘蛛中间件)

    蜘蛛中间件是介于Scrapy引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛的响应输入和请求输出。它提供一个自定义代码的方式来拓展Scrapy的功能。蛛中间件是一个挂接到Scrapy的蜘蛛处理机制的框架,你可以插入自定义的代码来处理发送给蜘蛛的请求和返回蜘蛛获取的响应内容和项目。

8、Scheduler middlewares(调度中间件)

    调度中间件是介于Scrapy引擎和调度之间的中间件,主要工作是处从Scrapy引擎发送到调度的请求和响应。他提供了一个自定义的代码来拓展Scrapy的功能。

二、数据处理流程

Scrapy的整个数据处理流程由Scrapy引擎进行控制,其主要的运行方式为:

  1. 引擎打开一个域名,时蜘蛛处理这个域名,并让蜘蛛获取第一个爬取的URL。
  2. 引擎从蜘蛛那获取第一个需要爬取的URL,然后作为请求在调度中进行调度。
  3. 引擎从调度那获取接下来进行爬取的页面。
  4. 调度将下一个爬取的URL返回给引擎,引擎将他们通过下载中间件发送到下载器。
  5. 当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎。
  6. 引擎收到下载器的响应并将它通过蜘蛛中间件发送到蜘蛛进行处理。
  7. 蜘蛛处理响应并返回爬取到的项目,然后给引擎发送新的请求。
  8. 引擎将抓取到的项目项目管道,并向调度发送请求。
  9. 系统重复第二部后面的操作,直到调度中没有请求,然后断开引擎与域之间的联系。

========================华丽的分割线========================

以上部分是属于网上抄过来的,谁是第一手就无可考究了,对于大家是否能看明白就没有保证了,我本还还算能够明白七成吧。

上面两个分割线中的内容也算得是回答了第一个问题了,那么为什么要用scrapy呢?我有一个习惯,在提出问题的时候都会先再找一个问题,对于这个问题而提出的问题是:我自己写一个不行吗?

刚开始的时候我也是这样想的,于是就自己开始找python怎么抓网页数据之类的了,后来还弄了一个不堪入目的一段代码,用于从一个根网页中找到所有的链接,然后将这些链接都放到一个列表中,然后弄个循环从这个列表中一个个去抓。下面就是我之前第一次接触python时写的代码(不堪入目,不喜勿喷。。。)

001 #encoding=utf-8
002
003 __author__ = 'dragon'
004
005 import urllib2
006 import os
007 import pymongo
008 import time
009 import hashlib
010
011 def myspider(startweb, keyword):
012     list = [startweb]
013     curindex = 0
014     Keyword = keyword
015
016     #网络上MongoHQ
017     #con = pymongo.Connection("paulo.mongohq.com", 10042)
018     #db = con.mytest
019     #db.authenticate("dragon", "dragon")
020     #db.urllist.drop()
021
022     #本地数据库
023     con = pymongo.Connection("localhost"27017)
024     db = con.mytest
025
026     while curindex < len(list):
027         url = list[curindex]
028         print "list count ="len(list), "  curcheck ", curindex
029         print "try to visit ", url
030
031         headers = ('User-Agent''Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36')
032
033         try:
034             opener = urllib2.build_opener()
035             opener.addheaders = [headers]
036             openness = opener.open(url, None30)
037             data = openness.read()
038             opener.close()
039         except:
040             print "some error ..."
041             curindex += 1
042             continue
043
044         print "finish get data..."
045
046         os.remove("d:/test.txt")
047         file = open("d:/test.txt""a")
048         print >> file, data
049         file.close()
050
051         myfile      = open("d:/test.txt""r")
052         mystring    = myfile.read()
053         myfile.close()
054
055         #找到标题
056         title       = ""
057         headstart   = mystring.find("<head>")
058         headend     = mystring.find("</head>")
059         if headstart < 0:
060             headstart   = mystring.find("<HEAD>")
061             headend     = mystring.find("</HEAD>")
062
063         if headstart > 0:
064             titlestart  = mystring.find("<title>")
065             titleend    = mystring.find("</title>")
066             if titlestart < 0:
067                 titlestart  = mystring.find("<TITLE>")
068                 titleend    = mystring.find("</TITLE>")
069
070             if titleend > titlestart and titlestart < headend and titleend < headend:
071                 title = mystring[titlestart+len("<title>"):titleend]
072
073         dbdata = {"title":"", "url":"", "time":""}
074
075         try:
076             title = title.decode("utf-8").encode("utf-8")
077         except:
078             try:
079                 title = title.decode("gbk").encode("utf-8")
080             except:
081                 pass
082
083
084         dbdata["title"= title
085         dbdata["url"= url
086         dbdata["time"= time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
087         try:
088             db.urllist.insert(dbdata)
089         except:
090             print "insert error"
091
092         if len(mystring) > 0:
093             while len(mystring) > 0:
094                 start = mystring.find("href=\"")
095                 if start <= 0:
096                     break
097
098                 substring = mystring[start+6:]
099                 end = substring.find("\"")
100                 weblink = substring[:end]
101                 if Keyword != "":
102                     if weblink.find(Keyword) >= 0 and list.count(weblink) <= 0:
103                         list.append(weblink)
104                 elif 0 > weblink.find("video.sina.com.cn") \
105                     and 0 > weblink.find("video.baidu.com") \
106                     and 0 <= weblink.find("http:") \
107                     and 0 >= list.count(weblink):
108
109                     list.append(weblink)
110
111                 mystring = mystring[start+6:]
112
113         curindex += 1
114
115 if __name__ == '__main__':
116     myspider("http://www.hao123.com""hao123")

处理的流程是:

    1. 将一个开始的网页url存放到list中

    2. 不断从list中取出url进行数据获取

    3. 在获取到的网页数据中的链接都存放到list里面

    4. 不断重复2、3步骤

上面这段代码写得怎么样就不值得评论了,但是值得我们思考的是,上面的代码出发点是爬虫,并且还是漫无目的的爬虫,没有了终点,或者大家会想到很多退出循环的方法,但是我们还有很多问题需要考虑:如何提高爬虫的效率?如何最大限度利用网络带宽?如果提高抓取回来数据的处理?最重要一点是:我们都不会想着去做google或百度,而是针对一些特定的需求来实现一个爬虫,那么我们如何简单而又快速的去实现我们的定制功能呢?

上面的几个问题就是我们最终都会遇到的问题,也是scrapy能够很好的处理的问题,它通过几个组件完成不同的部分,将类似下载网页数据的这些通用操作封装起来,减少了我们编写爬虫时的难度,并且各个部件之间通过异步来处理,能够最大限度利用了网络带宽。我们只需要按照它的要求来实现几个模块就可以了。

最后,讲讲使用如何生成一个scrapy工程。

打开cmd,cd到你要创建工程的目录,然后使用以下命令创建工程test:

    scrapy startproject test

如下图所示,我们看到创建了一个test文件夹,里面包含了其他一些文件

根据上图可以对照第一幅图,找到一些组件的对应文件,我们可以在spider下面创建一个py文件(例如:spider.py),然后写上以下代码:

1 from scrapy.spider import BaseSpider
2
3 class test(BaseSpider):
4     name = "test"
5     allowed_domains = ["hao123.com"]
6     start_urls = ["http://www.hao123.com"]
7
8     def parse(self, response):
9         print response.url
在cmd中,cd进入刚才创建的test目录,使用以下命令运行这个爬虫,我们可以最后看到一些debug输出

这篇文章到此为止,写得比较粗糙。可能大家对于spider.py中的一些变量和函数名称,以及该模块什么时候被调用存在疑问,大家可以上网找找资料学习,我将在下一篇文件中说明,并且以获取百度文库中的图书信息作为例子,完成相关的代码并提供源码。


目录
相关文章
|
4天前
|
数据采集 网络协议 API
HTTP协议大揭秘!Python requests库实战,让网络请求变得简单高效
【9月更文挑战第13天】在数字化时代,互联网成为信息传输的核心平台,HTTP协议作为基石,定义了客户端与服务器间的数据传输规则。直接处理HTTP请求复杂繁琐,但Python的`requests`库提供了一个简洁强大的接口,简化了这一过程。HTTP协议采用请求与响应模式,无状态且结构化设计,使其能灵活处理各种数据交换。
28 8
|
5天前
|
网络协议 安全 网络安全
震惊!Python Socket竟能如此玩转网络通信,基础到进阶全攻略!
【9月更文挑战第12天】在网络通信中,Socket编程是连接不同应用与服务的基石。本文通过问答形式,从基础到进阶全面解析Python Socket编程。涵盖Socket的重要性、创建TCP服务器与客户端、处理并发连接及进阶话题如非阻塞Socket、IO多路复用等,帮助读者深入了解并掌握网络通信的核心技术。
18 6
|
8天前
|
JSON API 开发者
Python网络编程新纪元:urllib与requests库,让你的HTTP请求无所不能
【9月更文挑战第9天】随着互联网的发展,网络编程成为现代软件开发的关键部分。Python凭借简洁、易读及强大的特性,在该领域展现出独特魅力。本文介绍了Python标准库中的`urllib`和第三方库`requests`在处理HTTP请求方面的优势。`urllib`虽API底层但功能全面,适用于深入控制HTTP请求;而`requests`则以简洁的API和人性化设计著称,使HTTP请求变得简单高效。两者互补共存,共同推动Python网络编程进入全新纪元,无论初学者还是资深开发者都能从中受益。
26 7
|
4天前
|
消息中间件 网络协议 网络安全
解锁Python Socket新姿势,进阶篇带你玩转高级网络通信技巧!
【9月更文挑战第13天】在掌握了Python Socket编程基础后,你是否想进一步提升技能?本指南将深入探讨Socket编程精髓,包括从阻塞到非阻塞I/O以提高并发性能,使用`select`进行非阻塞操作示例;通过SSL/TLS加密通信保障数据安全,附带创建SSL服务器的代码实例;以及介绍高级网络协议与框架,如HTTP、WebSocket和ZeroMQ,帮助你简化复杂应用开发。通过学习这些高级技巧,你将在网络编程领域更进一步。
17 2
|
6天前
|
机器学习/深度学习 人工智能 TensorFlow
深入骨髓的解析:Python中神经网络如何学会‘思考’,解锁AI新纪元
【9月更文挑战第11天】随着科技的发展,人工智能(AI)成为推动社会进步的关键力量,而神经网络作为AI的核心,正以其强大的学习和模式识别能力开启AI新纪元。本文将探讨Python中神经网络的工作原理,并通过示例代码展示其“思考”过程。神经网络模仿生物神经系统,通过加权连接传递信息并优化输出。Python凭借其丰富的科学计算库如TensorFlow和PyTorch,成为神经网络研究的首选语言。
11 1
|
7天前
|
API 开发者 Python
揭秘Python网络请求的幕后英雄:requests与urllib的恩怨情仇
【9月更文挑战第10天】在Python的网络请求领域,urllib与requests犹如武林中的两大高手,各自展现了独特的魅力。urllib作为标准库成员,自Python诞生以来便承担着网络请求的任务,以其稳定性和全面性著称。然而,其复杂的API让不少开发者望而却步。
11 2
|
8天前
|
数据采集 JavaScript 前端开发
构建你的首个Python网络爬虫
【9月更文挑战第8天】本文将引导你从零开始,一步步构建属于自己的Python网络爬虫。我们将通过实际的代码示例和详细的步骤解释,让你理解网络爬虫的工作原理,并学会如何使用Python编写简单的网络爬虫。无论你是编程新手还是有一定基础的开发者,这篇文章都将为你打开网络数据获取的新世界。
|
14天前
|
机器学习/深度学习 人工智能 算法
Python中实现简单神经网络
【9月更文挑战第2天】本文将通过Python编程语言,介绍如何从零开始构建一个简单的神经网络。我们将使用纯Python代码,不依赖任何外部库,来展示神经网络的核心概念和工作原理。文章将详细解释每个步骤,并最终实现一个能够进行基本模式识别的神经网络模型。通过这篇文章,读者可以对神经网络有一个直观的理解,并为进一步学习深度学习打下坚实的基础。
WK
|
15天前
|
数据采集 XML 安全
常用的Python网络爬虫库有哪些?
Python网络爬虫库种类丰富,各具特色。`requests` 和 `urllib` 简化了 HTTP 请求,`urllib3` 提供了线程安全的连接池,`httplib2` 则具备全面的客户端接口。异步库 `aiohttp` 可大幅提升数据抓取效率。
WK
34 1
|
17天前
|
机器学习/深度学习 人工智能 TensorFlow
深度学习入门:使用Python和TensorFlow构建你的第一个神经网络
【8月更文挑战第31天】 本文是一篇面向初学者的深度学习指南,旨在通过简洁明了的语言引导读者了解并实现他们的第一个神经网络。我们将一起探索深度学习的基本概念,并逐步构建一个能够识别手写数字的简单模型。文章将展示如何使用Python语言和TensorFlow框架来训练我们的网络,并通过直观的例子使抽象的概念具体化。无论你是编程新手还是深度学习领域的新兵,这篇文章都将成为你探索这个激动人心领域的垫脚石。