scrapy分为几个组成部分?分别有什么作用?

2020-07-30 09:52发布

2条回答
Anonyem
2楼 · 2020-10-15 14:11





  1. Scrapy框架的介绍

  2. scrapy是使用python编写的为了爬取网站数据,提取结构性数据而编写的一个应用框架,用途十分广泛。它是基于Twisted的一个异步处理框架,拥有架构清晰,可扩展性强,可灵活完成各种需求,各模块之间的耦合程度低,只需简单的几个模块就可以实现一个爬虫,因此上手很快。

  3. 1.1Scrapy工作机制

  4. 大体上可以将Scrapy中的模块分为下面几个:引擎(ScrapyEngine),调度器(Schedule),爬虫主件(Spider),下载器(Downloader),管道(ItemPipeline)。各模块之间相互配合,由此构成了一个框架的基本结构。框架的部分功能如下:引擎(ScrapyEngine),处理整个系统的数据流,出发事务,是整个框架的核心调度器(Schedule),接受引擎发过来的请求,并将其加入队列中,在引擎再次请求时将请求提供给引擎。爬虫主件(Spider),蜘蛛,在其内定义了爬取的逻辑以及网页的解析规则,主要是解析响应并提取数据和提供新的url下载器(Downloader),只有一个功能,就是发送请求获得响应管道(ItemPipeline),处理蜘蛛从网页中提取的数据,主要任务是清洗,验证与存储数据。可以选择将数据存在文件或数据库中。中间件(MiddleWare),有下载中间件以及爬虫中间件,其中在下载中间件中,我们可以设置user-agent,IP代理,cookie等以获得信息。

  5. 1.2Scrapy数据流向

  6. 在scrapy运行之后,它的数据流向大概是下面这个样子:

  7. Engine首先打开一个网站,找到处理该网站的Spider,并向该Spider请求第-个要爬取的URL。Engine从Spider中获取到第一个要爬取的URL,并通过Scheduler以Request的形式调度。Engine向Scheduler请求下一个要爬取的URL。Sceduler返回下一个要爬取的URL给Engine,Engine将URL通过DownloaderMiddlewares转发给Downloader下载。一旦页面下载完毕,Downloader生成该页面的Response,并将其通过DownloaderMiddlewares发送给Engine。Engine从下载器中接收到Response,并将其通过SpiderMiddlewares发送给Spider处理。Spider处理Response,并返回爬取到的Item及新的Request给Engine。Engine将Spider返回的Item给ItemPipeline,将新的Request给Scheduler。重复第(2)步到第(8)步,直到Scheduler中没有更多的Request,Engine关闭该网站,爬取结束。

  8. 通过多个组件的相互协作、不同组件完成工作的不同、组件对异步处理的支持,Scrapy最大限度地利用了网络带宽,大大提高了数据爬取和处理的效率。

  9. 1.3scrapy制作步骤

  10. 制作一个scrapy爬虫一共需要4步,

  11. 新建项目明确目标制作爬虫存储内容

  12. 1.4scrapy安装介绍

  13. Scrapy框架官方网址:http://doc.scrapy.org/en/latestScrapy中文维护站点:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.htmlWindows安装方式:通过pip安装Scrapy框架pipinstallScrapyUbuntu需要9.10或以上版本安装方式:安装非Python的依赖:

  14. sudoapt-getinstallpython-devpython-piplibxml2-devlibxslt1-dev

  15. zlib1g-devlibffi-devlibssl-dev

通过pip安装Scrapy框架sudopipinstallscrapy其他平台的安装可以见:scrapy各平台安装方法判断是否安装成功,在终端下输入scrapy命令,如果出现下面这种结果,说明已经成功。安装使用过程中的错误及解决办法:

使用Scrapy时遇到0:UserWarning:Youdonothaveaworkinginstallationoftheservice_identitymodule:‘cannotimportname‘opentype’’.Pleaseinstallitfrom…的问题解决网址:http://www.bubuko.com/infodetail-2467560.html报错cannotimportname“etree”原因是因为lxml版本过高,需卸载后重新安装3.8及以下的版本报错:MicrosoftVisualC++14.0isrequired.Getitwith“MicrosoftVisualC++BuildTools”…解决办法:前往http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted下载twisted对应版本的whl文件(如我的Twisted-18.4.0-cp36-cp36m-win_amd64.whl),cp后面是python版本,amd64代表64位,下载完毕后运行命令:pipinstallC:\Users\ibm\Downloads\Twisted-18.4.0-cp36-cp36m-win_amd64.whl报错:Nomodulenamed‘win32api’解决办法:pipinstallpywin32

2.Scrapy框架的使用

在scrapy使用过程中,项目的创建,执行均在终端进行,IDE只是一个编写代码的地方,不再运行scrapy项目。创建项目时,过程如下(以百度为例)打开终端:

scrapystartprojectbaidu

cddemoname

scrapygenspiderbaidubaidu.com


在这里介绍一下各文件的功能:

scrapy.cfg:它是Scrapy项目的配置文件,其内定义了项目的配置文件路径、部署相关信息等内容。items.py:它定义Item数据结构,所有的Item的定义都可以放这里。pipelines.py:它定义ItemPipeline的实现,比如数据的处理与保存。settings.py:它定义项目的全局配置。middlewares.py:它定义SpiderMiddlewares和DownloaderMiddlewares的实现。spiders包:其内包含一个个Spider的实现,每个Spider都有单独的一个文件。

打开项目中的settings文件,将是否遵守爬虫协议改为False

在修改过爬虫协议之后,已经可以从目标服务器获取关于网页的响应信息了。不信可以将response写入文件中试一试。获取响应内容要是用response.body或者response.text方式。如:可以看到start_urls为列表,在该列表中存储了需要爬取的网页的url,如果需要爬取的网页很少时可以选择直接将多个url存储在该列表。如果url规律可循可使用循环或者列表推导式来存储url。

拿到了网页的内容之后就是对网页内容的提取了,在scrapy中有自己的数据提取方法:Selector(选择器),它是基于lxml来构建的,支持xpath选择器以及css选择器,正则表达式,功能全面,解析速度很快,精确度也很高。当然在框架外也是可以使用Selector选择器的,这样提取数据的方法又多了一种。

由于selector支持xpath,所以在拿到响应后,不需要做其他的处理就可以直接用xpath中的方法来提取结构化数据。而且在上面也讲过,在提取数据的时候有两部分结果,一个是需要交给管道进行下一步处理的数据,另一个是需要进一步爬取的网站的url。因为只有一个蜘蛛在进行工作,所以在这里就用到了生成器的相关知识,如果不熟悉,可以去找基础知识翻看。一般情况下,对这种情况我们是这样处理的,使用多个yield,一步一步的完成网页的爬取与数据提取。而对于数据的存储,则需要创建一个item对象,由它将数据携带给管道进行处理。

比如下面这个例子(爬取golang贴吧):

extract_first()是将匹配的第一个结果取出来,如果没有取到,也不会报错;extract()是将匹配的全部结果以列表形式返回,仍需索引值来取出数据;response.urljoin()可以将相对路径转为绝对路径,很好用,不用费劲的去拼接url,一个不小心还会拼错;response.url返回的是当前的url。

spider包中的spider.py文件的代码:

classGolangSpider(scrapy.Spider):

name='golang'

allowed_domains=['baidu.com']

start_urls=['https://tieba.baidu.com/f?kw=golang&ie=utf-8&pn=0']

defparse(self,response):

print('*****************************'*100,response.url)

li_list=response.xpath(r'.//li[@class="j_thread_listclearfix"]')

forliinli_list:

item=GolangSpiderItem()

title=li.xpath(r'.//a[@class="j_th_tit"]/text()').extract_first()

item['title']=title

author=li.xpath(r'.//span[@class="frs-author-name-wrap"]/a/text()').extract_first()

item['author']=author

time=li.xpath(r'.//span[@class="pull-rightis_show_create_time"]/text()').extract_first().strip()

item['time']=time

#href='https://tieba.baidu.com'+li.xpath(r'.//a[@class="j_th_tit"]/@href').extract_first()

href=response.urljoin(li.xpath(r'.//a[@class="j_th_tit"]/@href').extract_first())

yieldscrapy.Request(url=href,callback=self.parser2,meta={'data':item})

next_page=response.xpath('.//div[@id="frs_list_pager"]/a[@class="nextpagination-item"]/@href')

ifnext_page:

next_page=response.urljoin(next_page.extract_first())

yieldscrapy.Request(url=next_page,callback=self.parse)

defparser2(self,contents):

print('进入了:',contents.url,'页面')

item=contents.meta.get('data')

content=contents.xpath('.//div[@class="d_post_contentj_d_post_content"]/text()').extract()

i=''

n=1

forlincontent:

floor='第{}楼:'.format(n)

i=i+floor+l.strip()

n+=1

item['content']=i

print(contents.url)

yielditem


在items.py文件中,items.py中定义了各爬虫相对应的Item类,继承scrapy.Item类,每一个字段都是scrapy.Field()的对象。在pipelines.py文件中定义了关于数据的处理方式。到底是丢弃还是去重还是保存。在使用之前先要在settings.py文件中将有关itempipeline的设置打开。注意在这里key值由三个部分组成,包名,文件名,类名。不要写错,value值为数字,在1-1000之间取值,值越小优先级越高。pipelines.py文件中对数据的处理可以见下面的代码:

如果是写入文件中有下面两种写法

第一种方法:

classGolangSpiderPipeline(object):

def__init__(self):

os.remove('baidu.json')

self.file=open('baidu.json','a',encoding='utf-8')

defprocess_item(self,item,spider):

str=json.dumps(dict(item),ensure_ascii=False)+''

self.file.write(str)

#json.dump(dict(item),open('tieba.json','a',encoding='utf-8'),ensure_ascii=False)

returnitem

defclose_spider(self,spider):

self.file.close()

第二种方法:

classGolangSpiderPipeline(object):

defprocess_item(self,item,spider):

fp=open('tieba.json','a',encoding='utf-8')

json.dump(dict(item),fp,ensure_ascii=False)

fp.write('')

returnitem


如果是存入数据库可以见下面的代码(以MongoDB为例):

classGolangSpiderPipeline(object):

def__init__(self):

#连接数据库,库和表如果没有会自动创建

self.client=pymongo.MongoClient('localhost',27017)

#选择库名

self.db=self.client['Golang']

#查询数据db.baidu.find()

#使用数据库usedbname

defprocess_item(self,item,spider):

#baidu为库中的表名

self.db.baidu.insert(dict(item))

returnitem

defclose_spider(self,spider):

self.client.close()


到此,一个完整的爬虫框架已经结束了,在没有反爬措施的网站中,是完全可以提取到我们想要的各种信息的。

3.Logging

Scrapy提供了log功能,可以通过logging模块使用。可以修改配置文件settings.py,任意位置添加下面两行,效果会清爽很多。

LOG_FILE="baidu.log"

LOG_LEVEL="INFO"


LoglevelsScrapy提供5层logging级别:CRITICAL-严重错误(critical)ERROR-一般错误(regularerrors)WARNING-警告信息(warningmessages)INFO-一般信息(informationalmessages)DEBUG-调试信息(debuggingmessages)设置了级别之后,该日志文件便只会记录此等级及以上的错误日志。

logging设置通过在setting.py中进行以下设置可以被用来配置logging:LOG_ENABLED默认:True,启用loggingLOG_ENCODING默认:‘utf-8’,logging使用的编码LOG_FILE默认:None,在当前目录里创建logging输出文件的文件名LOG_LEVEL默认:‘DEBUG’,log的最低级别LOG_STDOUT默认:False如果为True,进程所有的标准输出(及错误)将会被重定向到log中。例如,执行print“hello”,其将会在Scrapylog中显示。


曾为
3楼 · 2020-08-02 22:34

分为5个部分;Spiders(爬虫类),Scrapy Engine(引擎),Scheduler(调度器),Downloader(下载器),Item Pipeline(处理管道)。

  • Spiders:开发者自定义的一个类,用来解析网页并抓取指定url返回的内容。

  • Scrapy Engine:控制整个系统的数据处理流程,并进行事务处理的触发。

  • Scheduler:接收Engine发出的requests,并将这些requests放入到处理列队中,以便之后engine需要时再提供。

  • Download:抓取网页信息提供给engine,进而转发至Spiders。

  • Item Pipeline:负责处理Spiders类提取之后的数据。 比如清理HTML数据、验证爬取的数据(检查item包含某些字段)、查重(并丢弃)、将爬取结果保存到数据库中


相关问题推荐

  • 回答 3

    换行。比如,print hello\nworld效果就是helloworld\n就是一个换行符。\是转义的意思,'\n'是换行,'\t'是tab,'\\'是,\ 是在编写程序中句子太长百,人为换行后加上\但print出来是一整行。...

  • 回答 42

    十种常见排序算法一般分为以下几种:(1)非线性时间比较类排序:a. 交换类排序(快速排序、冒泡排序)b. 插入类排序(简单插入排序、希尔排序)c. 选择类排序(简单选择排序、堆排序)d. 归并排序(二路归并排序、多路归并排序)(2)线性时间非比较类排序:...

  • 回答 70
    已采纳

    前景很好,中国正在产业升级,工业机器人和人工智能方面都会是强烈的热点,而且正好是在3~5年以后的时间。难度,肯定高,要求你有创新的思维能力,高数中的微积分、数列等等必须得非常好,软件编程(基础的应用最广泛的语言:C/C++)必须得很好,微电子(数字电...

  • 回答 28

    迭代器与生成器的区别:(1)生成器:生成器本质上就是一个函数,它记住了上一次返回时在函数体中的位置。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。而且记录了程序执行的上下文。生成器不仅记住了它的数据状态,生成器还记住了程序...

  • 回答 9

    python中title( )属于python中字符串函数,返回’标题化‘的字符串,就是单词的开头为大写,其余为小写

  • 回答 6

    第一种解释:代码中的cnt是count的简称,一种电脑计算机内部的数学函数的名字,在Excel办公软件中计算参数列表中的数字项的个数;在数据库( sq| server或者access )中可以用来统计符合条件的数据条数。函数COUNT在计数时,将把数值型的数字计算进去;但是...

  • 回答 1

    head是方法,所以需要取小括号,即dataset.head()显示的则是前5行。data[:, :-1]和data[:, -1]。另外,如果想通过位置取数据,请使用iloc,即dataset.iloc[:, :-1]和dataset.iloc[:, -1],前者表示的是取所有行,但不包括最后一列的数据,结果是个DataFrame。...

  • Python入门简单吗2021-09-23 13:21
    回答 45

    挺简单的,其实课程内容没有我们想象的那么难、像我之前同学,完全零基础,培训了半年,直接出来就工作了,人家还在北京大公司上班,一个月15k,实力老厉害了

  • 回答 4

    Python针对众多的类型,提供了众多的内建函数来处理(内建是相对于导入import来说的,后面学习到包package时,将会介绍),这些内建函数功用在于其往往可对多种类型对象进行类似的操作,即多种类型对象的共有的操作;如果某种操作只对特殊的某一类对象可行,Pyt...

  • 回答 8

     相当于 ... 这里不是注释

  • 回答 4

    还有FIXME

  • 回答 3

    python的两个库:xlrd和xlutils。 xlrd打开excel,但是打开的excel并不能直接写入数据,需要用xlutils主要是复制一份出来,实现后续的写入功能。

  • 回答 8

    单行注释:Python中的单行注释一般是以#开头的,#右边的文字都会被当做解释说明的内容,不会被当做执行的程序。为了保证代码的可读性,一般会在#后面加一两个空格然后在编写解释内容。示例:#  单行注释print(hello world)注释可以放在代码上面也可以放在代...

  • 回答 2

    主要是按行读取,然后就是写出判断逻辑来勘测行是否为注视行,空行,编码行其他的:import linecachefile=open('3_2.txt','r')linecount=len(file.readlines())linecache.getline('3_2.txt',linecount)这样做的过程中发现一个问题,...

  • 回答 4

    或许是里面有没被注释的代码

  • 回答 26

    自学的话要看个人情况,可以先在B站找一下视频看一下

没有解决我的问题,去提问