• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

PYTHON 改变世界

学海无涯,苦作舟
  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

爬虫_小结02

 

1、scrapy框架专题部分

(1)请简要介绍下scrapy框架。
scrapy 是个快速,高层次的基于python的web爬虫框架,用于抓取web站点,并从页面中提取结构化的数据。
scrapy使用了Twisted异步网络库来处理网络通信。

(2)为什么要使用scrapy框架?scrapy框架有哪些优点?
它更容易构建大规模的抓取项目
它异步处理请求,速度非常快
它可以使用自动调节机制自动调整爬行速度

(3)scrapy框架有哪几个组件/模块?简单说一下工作流程。

Scrapy Engine: 这是引擎,负责Spiders、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等等

Scheduler(调度器): 它负责接受引擎发送过来的requests请求,并按照一定的方式进行整理排列,入队、并等待Scrapy Engine(引擎)来请求时,交给引擎。

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

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

Item Pipeline:它负责处理Spiders中获取到的Item,并进行处理,比如去重,持久化存储(存数据库,写入文件,总之就是保存数据用的)

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

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

(4)scrapy如何实现分布式抓取?
可以借助scrapy_redis类库来实现。

原理:
在分布式爬取时,会有master机器和slave机器,其中,master为核心服务器,slave为具体的爬虫服务器。
在master服务器上搭建一个redis数据库,并将要抓取的url存放到redis数据库中,所有的slave爬虫服务器在抓取的时候从redis数据库中获取链接,
由于scrapy_redis自身的队列机制,slave获取的url不会相互冲突,然后抓取的结果最后都存储到数据库中。
master的redis数据库中还会将抓取过的url的指纹存储起来,用来去重。相关代码在dupefilter.py文件中的request_seen()方法中可以找到。

去重问题:
dupefilter.py 里面的源码:
def request_seen(self, request):
  fp = request_fingerprint(request)
  added = self.server.sadd(self.key, fp)
return not added
去重是把 request 的 fingerprint 存在 redis 上,来实现的。


2、其他常见问题。
(1)爬虫使用多线程好?还是多进程好?为什么?
对于IO密集型代码(文件处理,网络爬虫),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,会造成不必要的时间等待,
而开启多线程后,A线程等待时,会自动切换到线程B,可以不浪费CPU的资源,从而提升程序执行效率)。
在实际的采集过程中,既考虑网速和相应的问题,也需要考虑自身机器硬件的情况,来设置多进程或者多线程。


(2)http和https的区别?
A. http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
B. http适合于对传输速度、安全性要求不是很高,且需要快速开发的应用。如web应用,小的手机游戏等等。而https适用于任何场景。


(3)数据结构之堆,栈和队列的理解和实现
栈(stacks):栈的特点是后进先出。只能通过访问一端来实现数据的储存和检索的线性数据结构。
队列(queue):队列的特点是先进先出。元素的增加只能在一端,元素的删除只能在另一端。增加的一端称为队尾,删除的一端称为队首

栈:
stack = [1, 2, 3]
stack.append(4)
stack.append(5)
print(stack) # [1, 2, 3, 4, 5]
stack.pop()
stack.pop()
print(stack) # [1, 2, 3]

队列:
from collections import deque

queue = deque(['Eric', 'John', 'Michael'])
queue.append('Terry')
queue.append('Graham')
print(queue) # deque(['Eric', 'John', 'Michael', 'Terry', 'Graham'])
queue.popleft()
print(queue) # deque(['John', 'Michael', 'Terry', 'Graham'])

栈溢出的几种情况?
1、局部数组过大。当函数内部数组过大时,有可能导致堆栈溢出。
2、递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致堆栈溢出。

解决方法:
1、用栈把递归转换成非递归。
2、增大栈空间。

 

posted on 2019-05-09 22:01  ALLEN&Y  阅读(102)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3