感觉我需要先把Scrapy官方文档再过一遍,
收集了一下网上的scrapy面试题,发现面试会碰到什么情况的问题也真的是无法预料。

前言

只说一句,官方文档万岁。

Scrapy QA

对网上见过的问题,进行知识点整理。

Scarapy 数据流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
基本必问,脑海里最好有一张流程图

1. Engine获得从爬行器中爬行的初始请求。
2. Engine在调度程序中调度请求,并请求下一次抓取请求。
3. 调度程序将下一个请求返回到引擎。
4. 引擎将请求发送到下载器,通过下载器中间件(请参阅process_request())。
5. 页面下载完成后,下载器生成一个响应(带有该页面)并将其发送给引擎,通过下载器中间件(请参阅process_response())。
6. 引擎从下载加载程序接收响应,并将其发送给Spider进行处理,并通过Spider中间件(请参阅process_spider_input())。
7. Spider处理响应,并向引擎返回报废的项和新请求(要跟踪的),通过Spider中间件(请参阅process_spider_output())。
8. 引擎将已处理的项目发送到项目管道,然后将已处理的请求发送到调度程序,并请求可能的下一个请求进行抓取。
9. 这个过程重复(从第1步),直到调度程序不再发出请求。

简单总结:
start_request(引擎)>调度器>引擎>(下载中间件)>下载器>(下载中间件)>引擎>(爬虫中间件)>爬虫>(爬虫中间件)>引擎>管道&&调度器> more

Scrapy相BeautifulSoup或lxml比较,如何呢?

1
2
3
4
5
6
7
8
BeautifulSoup 及 lxml 是HTML和XML的分析库。
Scrapy则是 编写爬虫,爬取网页并获取数据的应用框架(application framework)。

Scrapy提供了内置的机制来提取数据(叫做 选择器(selectors))。
但如果您觉得使用更为方便,也可以使用 BeautifulSoup (或 lxml)。
总之,它们仅仅是分析库,可以在任何Python代码中被导入及使用。

换句话说,拿Scrapy与 BeautifulSoup (或 lxml) 比较就好像是拿 jinja2 与 Django 相比。

Scrapy支持HTTP代理么?

1
必须的,通过 HttpProxyMiddleware 中间件可以实现。当然也可以通过自定义中间件来实现!

Scrapy如何爬取属性在不同页面的item呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
非常基础且常见的问题..
通过response的meta来进行传递,字典键值对。不但是item,就算是一些自定义参数也可以传。

除了meta,有趣的还有其他特殊方法:
dont_redirect
dont_retry
handle_httpstatus_list
handle_httpstatus_all
dont_merge_cookies (see cookies parameter of Request constructor)
cookiejar dont_cache
redirect_urls
bindaddress
dont_obey_robotstxt
download_timeout
download_maxsize
proxy

顾名思义,估计也能猜出来了。
这里我用最多还有redirect_urls和dont_retry,控制跳转以及控制是否重试。
结合retry或者重定向中间件,还可以针对性的处理爬取过程中碰到的验证码问题。
高端点的还有cookie合并方法。

Scrapy我要如何在spider里模拟用户登录呢?

1
2
使用FormRequest.from_response()方法
构造好需要用户登录需要的各类参数,然后模拟用户登录。

Scrapy是以广度优先还是深度优先进行爬取的呢?

1
2
3
4
5
6
7
8
9
默认情况下,Scrapy使用 LIFO 队列来存储等待的请求。
简单的说,就是 深度优先顺序 。
深度优先对大多数情况下是更方便的。
如果您想以 广度优先顺序 进行爬取,你可以设置以下的设定:
DEPTH_PRIORITY = 1
SCHEDULER_DISK_QUEUE = 'scrapy.squeue.PickleFifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeue.FifoMemoryQueue'

DEPTH_LIMIT 还可以对层级进行有效的限制,根据项目情况来定。

Scrapy爬虫有内存泄露/内存爆了/栈溢出了,怎么办?

1
2
3
4
5
6
7
8
9
10
加内存条啊(这句话划掉)

解决方案:没有比这更详细的了。
https://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/leaks.html#topics-leaks

我的步骤是这样的:
1. 首先检查编写的中间件,管道(pipeline) 或扩展。例如,在 spider_opened 中分配资源但在 spider_closed 中没有释放它们。
2. 检查是否出现下载速度和管道存储速度是否平衡,如果差距很大,会造成队列积压。
3. 使用 trackref 在telNet下调试内存泄露,具体问题具体分析,其追踪了所有活动(live)的Request, Item及Selector对象的引用。
4. 使用 get_oldest() 方法来看都是什么鬼东西在那卡半天,找出来单独测试然后寻找解决办法。

如何让Scrapy减少内存消耗?

1
2
3
4
5
6
加内存条啊(这句话划掉)

1. 尽可能减少对 meta 或者 request回调函数 的传递对象的引用
2. 让Requests, Response及Items的对象具有完整有限的生命周期: 被创建,使用,最后被销毁。尤其是销毁!
3. 中间件,管道(pipeline) 或扩展.py 中,一定要有有始有终。记得在 spider_closed 中没有释放分配的资源。

spider中可以使用基本HTTP认证么?

1
HttpAuthMiddleware 有关的验证中间件,了解一下。

(未完持续..)