从零开始的Scrapy爬虫

从零开始的Scrapy爬虫

学中做、做中学比直接看教材强多了,从 Scrapy 开始学爬虫和 Python 也比单纯学 Python 上手要快得多。权当笔记记录一下自己的学习。本文使用 Python3.11

本文的所有内容都是 Windows-only,等你打算给我买 Mac 了再问为什么

什么是爬虫

网络爬虫始于一张被称作种子的统一资源地址(URL)列表。当网络爬虫访问这些统一资源定位器时,它们会甄别出页面上所有的超链接,并将它们写入一张 “待访列表”,即所谓爬行疆域。此疆域上的 URL 将会被按照一套策略循环来访问。

网络爬虫 - 维基百科

简而言之,爬虫就是在规定的范围内,对对象进行有序、不重复提取的自动机器人。

但是大范围的网络爬取对技术和系统性能的要求都不小,在此暂时不做探讨。

为什么要从 Python 开始学爬虫

爬虫不是 Python 的特权。不论是 Java 还是 C++,甚至是 C 语言,理论上只要能进行或模拟网络请求的语言都可以写一个爬虫出来。选用 Python 单纯就是因为它适合初学者:

  • 弱数据类型
    • 不用你忙着指定什么 int/long int/short intfloat/doublechar 之类的东西,上手简单得多
  • 语法易理解
    • 在进行循环时,C 语言可能要将循环的头写成这样:for(int i = 0; i <= 10; i++);但 Python 可能只需要这么写:for num in nums,比 C 好理解得不是一星半点。
  • 应该还有别的优点,但是我编不出来了。

别问那么多了,总之就是简单。反正至少比 C 简单。

为什么选 Scrapy

像上一部分说的那样,不用 Scrapy 也是完全可行的:网上大把成熟不成熟的框架,根本不用你发愁;嫌弃框架太小儿科还可以直接用 Python 的 Request 模块把页面下载下来搭配 BeautifulSoup 这样老牌又成熟的库爬取页面;或者你自己从零开始造轮子也完全没问题,不过你都自己造轮子了为什么不试试用汇编写爬虫(

Scrapy 提供了什么

  • 优秀(但受限于 Python 自身的原因可能在网络请求上不够极端高效)的框架
  • 翔实的文档
  • 丰富可拓展的配置
  • 完整易懂的爬虫工作流
  • 后边忘了总之很强。

从零开始

第一步:用Win+R组合键打开“运行”

  • 下载一条 Python [从官网]
  • 安装一条 Python [完整教程]
  • 在“运行”中输入 cmd 并回车,打开 CMD
  • 运行 cd [你的项目文件夹] 来进入项目文件夹
  • 在 CMD 中输入 pip install Scrapy 并运行
    • 嫌下载慢可以换源或者使用其他奇技淫巧,在此不多赘述
  • 在 CMD 中输入 scrapy startproject tutorial 并运行
  • 现在你已经成功创建了自己的第一个爬虫程序,本文结束。

当然了,只创建一个项目是什么都爬不下来的。

第二步:创建一个爬虫

  • 在 CMD 中输入 cd tutorial 并运行
  • 在 CMD 中输入 scrapy genspider sp smokingpipes.com 并运行
    • 挑了个商铺网站,其他网站基本大同小异

现在你已经建立好了一个爬虫,但是别急着运行,点开项目文件夹下的这个文件:

1
2
3
4
.
└───tutorial
└───spiders
└───sp.py <---这个文件

你会在其中看到这样的代码:

1
2
3
4
5
6
7
8
9
import scrapy

class SpSpider(scrapy.Spider):
name = "sp"
allowed_domains = ["smokingpipes.com"]
start_urls = ["https://smokingpipes.com"]

def parse(self, response):
pass

在这其中,有以下几点要说明:

  • import scrapy

    • 导入模组,这在许多语言中都有。
    • 这句话的意思是,从默认路径下(因为并没有指定这个 scrapy 从哪来,那自然就是去默认路径下找喽)引入一个叫 scrapy 的玩意。
      • 引入
        • 举个例子,你去参加三级笔译考试(这考试是允许带词典的),带了本韦氏大词典,碰到不会的词你去查,查完你就知道这句话怎么翻译了。
        • 这里也是同理:电脑运行这个程序,本来没带词典(未引入模组),结果碰到没见过的词之后卡住了,抓耳挠腮一通想啊,头发揪完了都没想出来;这时候你递给它一本词典(模组),告诉它:“你那些个词这本词典上都有,你查查”,然后电脑就发现:“原来这B词这么简单啊”,就能顺利完成你交代给它的工作了。
  • class SpSpider(scrapy.Spider)

    • 新建一个类,这是面向对象语言中独有的一种思想。
    • 这句话的意思是,新建一个叫做 SpSpider 的类,其继承自每个爬虫都必须继承的 scrapy.Spider 类。
      • scrapy.Spider 是个什么类?我也不懂,但是这个类规定了一个爬虫该有的功能、该接受的参数。
      • 之后的代码都是父类(也就是其继承的类)中规定过的功能之具体实现。
  • name = "sp"

    • 规定了爬虫独一无二的名字。

    • 这是一行赋值语句,把等号右边的值赋给左边的变量。

      • 在 Python 中,一个变量可以存储任意类型的值,在数据存储上的意义在我看来可以视同 C 语言中的指针:只指向值,自身没有任何条条框框。

      • 这里的 name 是一个变量,其无需事先声明,在赋值时会直接生成

        • 在 Python3.x 的某个版本中新增了 := 这个被称为“海象运算符”的符号,可以在为变量赋值的同时返回变量的值,比如:
          1
          2
          3
          4
          5
          6
          beta = 3
          if (alpha := beta) is Not None:
          # is Not None 这种用法已经逐渐被抛弃,
          # 推荐使用更加现代化的 != None
          # Python 中以井号开头做为注释
          alpha = 2 * alpha
          这里会新建一个变量 alpha,并将 beta 的值赋给它,再进行 if 判断。而 None 是 Python 中的特殊变量,代表“空”,意指其中没有任何值。
      • 这里的 "sp" 是一个字符串值。Python 中没有单独的字符数据类型,字符被视为只有一个字符的字符串。

  • allowed_domains = ["smokingpipes.com"]

    • 规定了允许爬虫爬取的网站,也就是前述的“爬取疆域”。
    • 右侧中括号 [] 及其内部字符共同组成了一个“列表”,现在列表中只有一个字符串元素。
  • start_urls = ["https://smokingpipes.com"]

    • 规定了爬虫开始爬取的首个网站。
    • ** 强烈建议在真实爬取之前先将目标网页下载至本机,然后将双引号中的内容改为 file:///[你下载好的网页的html文件的位置] **,这样不但可以快速获得你每次调试的结果,还可以防止你在正式上线爬虫之前 IP 就被网站封禁。
  • def parse(self, response):

    • 定义一个函数
    • def 指的是 ‘define’,也就是定义,此处定义了一个名叫 parse 的函数,其会接受两个参数,分别是 selfresponseself 意指其可以接受类中、函数外部的全局变量,而 response 指的是其在被调用前由框架自动下载好的 start_urls 中网页的内容。
    • 在这个函数内部,会对下载好的(已爬取)的网页进行处理。
  • pass

    • 将结果传给流程中的下一阶段
    • 因为我们暂时没有对网页内容进行处理,因此 Scrapy 框架缺省为我们配置了这一语句防止出错。

缺省爬虫就这么简单。