最近一直都是在用自己写的抓取框架做爬虫,还是系统的整理一下Scrapy相关的知识,做一个old school 的爬虫。
爬虫的整个流程,就是发送网络请求,处理返回的内容两个过程。然后我们将这个流程细化;如何准备需要访问的链接,需要访问的链接应该是哪些链接;发送请求时我们带上什么,如何更快的发送更多请求;对返回的内容需要做哪些操作……
不讲实例,只看实现。从Scrapy的源码来读Scrapy到底是如何执行这些流程,就当睡前读物,毕竟技多不压身。
Scrapy文档:https://docs.scrapy.org/en/latest/
Scrapy官网:https://scrapy.org/
Scrapy目录结构:scrapy目录下的基本就是我要找到的各种实现,*.py文件再从各目录下进行import全部模块。
启动部分:
从我记忆里Scrapy的启动方式一步步来看,首先看scrapy的命令行是怎么运行起来的。cmdline.py和command.py两个文件。command.py从commands文件夹中导入,commands文件夹下的就是常见的各种命令,描述着当我们在命令行下调用这些命令时会发生什么。init.py文件里是所以命令的基类ScrapyCommand。而这一些都是通过cmdline.py中来执行的,当我们最开始下载完Scrapy后在命令行输入scrapy时。
我们可以从命令行里看到上面的结果,而这一切都是在cmdline.py中进行操作的。当cmdline.py运行时,会调用execute方法。
(1)当不带参数或带上了错误参数
execute方法最开始会获取最近的项目配置并加载,因为我此前并不在某个项目下,所以输出no active project。(图中inproject是一个bool值,在utils\conf.py中寻找scrapy.cfg文件,如果不存在则往上一级查找,查看现在是否在某个项目下。)
cmds是对commands文件夹下的各个命令进行加载,cmdname是对当前参数中的命令进行验证。
当不带任何参数的时候,调用_print_commands方法。方法里的代码是不是似曾相识,就是我们直接在命令行输入scrapy显示的内容。
def _print_commands(settings, inproject):
_print_header(settings, inproject)
print("Usage:")
print(" scrapy <command> [options] [args]\n")
print("Available commands:")
cmds = _get_commands_dict(settings, inproject)
for cmdname, cmdclass in sorted(cmds.items()):
print(" %-13s %s" % (cmdname, cmdclass.short_desc()))
if not inproject:
print()
print(" [ more ] More commands available when run from project directory")
print()
print('Use "scrapy <command> -h" to see more info about a command')
(2)当带上正确参数
cmds中已经获取cmd对象,根据传入的参数获取对应的cmd对象。注意的是两个_run_print_help方法;第一个是执行cmd的process_options方法,对cmd对象的setting进行一些初始化的设置(如log文件位置,等级的一些设置);设置好之后给cmd设置crawler_process对象。第二个是_run_command方法,通过传入的cmd执行对应的run方法。