通过前几节的学习,我们已经了解了Scrapy的基本操作,下面我们开始第一个项目,我以本人的网址为例进行爬虫讲解,之所以用我自己的网站,是因为我这个网站本来就是做知识分享用的,共大家学习,不会去限制爬取,现在很多网站为了防止爬虫,都会做很多限制策略,不适合新手练习,本人就提供这样一个练习平台给大家。当然维护网站不易,如果你学到了知识,也请给作者一杯咖啡的钱谢谢🙏。
注:本教程的所有代码均在windows上完成的,其他系统文件路径或系统相关命令可以会有区别。
Scrapy目录结构
我们先回过头,再看下Scrapy目录结构,这次要说明的就不是根目录和项目目录的作用了,而是要对每个文件及目录进行下说明,开始编写我们的第一个爬虫。
首先使用命令创建爬虫项目,我的网站主要是做知识内容分享的,所以项目名称就叫KnowledgeSharing,使用命令创建如下
scrapy startproject KnowledgeSharing
|
爬取的网页就是首页,我们爬虫名就叫shouye,使用命令创建如下
cd KnowledgeSharing scrapy genspider shouye www.jayhgq.cn
|
执行以上命令后,我们会得到以下目录,我在每个文件后面加了注释,解释这个文件的作用。
├─KnowledgeSharing │ │ scrapy.cfg │ │ │ └─KnowledgeSharing │ │ items.py │ │ middlewares.py │ │ pipelines.py │ │ settings.py │ │ __init__.py │ │ │ ├─spiders │ │ │ shouye.py │ │ │ __init__.py
|
第一个爬虫
知道了Scrapy的目录结构,我们可以动手开始做我们的第一个爬虫了,从目录结构中能看到,爬虫规则是写在spiders文件夹下的爬虫代码文件中,刚创建的第一个爬虫代码文件叫shouye.py
,我们打开这个文件,可以看到以下内容,同样我为代码加上了注释,一定要仔细看注释,不然后面可能有些内容会不清楚。
import scrapy
class ShouyeSpider(scrapy.Spider): name = "shouye" allowed_domains = ["www.jayhgq.cn"] start_urls = ["https://www.jayhgq.cn"]
def parse(self, response): pass
|
以上是用scrapy的genspider命令自动生成的,但是这样我们执行什么都存储不下来,我们来做下简单的改动,如下
from pathlib import Path import scrapy
class ShouyeSpider(scrapy.Spider): name = "shouye" allowed_domains = ["www.jayhgq.cn"] start_urls = ["https://www.jayhgq.cn"]
def parse(self, response): filename = 'shouye.html' Path(filename).write_bytes(response.body) self.log(f"成功保存文件 {filename}")
|
运行爬虫
将代码做改写后,我们如何运行它呢,很简单,还记得前讲过的crawl命令吗?没错,就用它。
使用crawl命令有个条件就是必须在爬虫程序目录执行,因为它是一个Project-only Commands。进入到爬虫程序目录后,执行scrapy crawl shouye
命令,可以看到如下输出。
> cd KnowledgeSharing\KnowledgeSharing > scrapy crawl shouye 2024-11-19 22:38:25 [scrapy.utils.log] INFO: Scrapy 2.11.2 started (bot: KnowledgeSharing) ...(此处省略一堆输出日志) 2024-11-19 22:38:25 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.offsite.OffsiteMiddleware', 'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2024-11-19 22:38:25 [scrapy.middleware] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2024-11-19 22:38:25 [scrapy.middleware] INFO: Enabled item pipelines: [] 2024-11-19 22:38:25 [scrapy.core.engine] INFO: Spider opened ...(此处省略一堆输出日志) 2024-11-19 22:38:25 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.jayhgq.cn> (referer: None) 2024-11-19 22:38:25 [shouye] DEBUG: 成功保存文件 shouye.html ...(此处省略一堆输出日志) 2024-11-19 22:38:25 [scrapy.core.engine] INFO: Spider closed (finished)
|
命令执行完后,到我们的爬虫程序目录,可以看到一个名字为shouye.html
的文件,如图,这就是我们刚才通过代码存下来的内容,其本质就是我们浏览器渲染的html文件,只是没有css和js文件,如果用浏览器打开只是一些文字和链接,非常难看。

必要说明
如果你教程看到这,恭喜你,已经可以完成一次爬虫了。
大家可能会有疑问,爬虫这么简单吗?笔者想说,就是这么简单,但是,还有但是,爬虫并不仅如此,还有很多内容,比如如何提取数据、如何持久化数据、如何添加相关请求参数、如何设置中间件等等。
在进行后面的讲解前,我们先对上面的代码进行下补充说明。
start_requests()和start_urls
在上面的代码中我们用了start_urls
来设置了初始的url,在Scrapy中还有一种定义的方法start_requests()
。
def start_requests(self): urls = [ "https://www.jayhgq.cn/2024/11/05/python-huan-jing-an-zhuang/", "https://www.jayhgq.cn/2024/11/17/scrapy-scrapy-jiao-cheng-1-jian-jie/", ] for url in urls: yield scrapy.Request(url=url, callback=self.parse)
|
这种方法和start_urls
定义一样,因为Scrapy启动时,如果没有检测到start_requests()
方法,会默认从start_urls
列表中获取初始请求url,但是如果你写了start_requests()
方法,start_urls
就不起作用了。
还有如果你要修改首次请求的方法,比如实现POST方法的请求登录,这时需要传参,就要重构start_requests()
方法实现,因为start_requests()
方法可以让你灵活的控制每个请求。这里先提供简单的示例,后面实际用到时在详细说明。
import scrapy class MySpider(scrapy.Spider): name = "my_spider" def start_requests(self): headers = {'User - Agent': 'Mozilla/5.0'} urls = ["http://example.com/page1", "http://example.com/page2"] for url in urls: yield scrapy.Request(url, headers = headers, callback=self.parse) def start_requests(self): return [ scrapy.FormRequest( "http://www.example.com/login", formdata={"user": "john", "pass": "secret"}, callback=self.logged_in, ) ] def parse(self, response): pass
|
如何关闭allowed_domains的限制
代码注释中提到allowed_domains的限制是默认开启,那如何关闭呢?可以到settings.py中找到对应的中间件,加入这行代码'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': None
即可关闭,但是这样会造成Scrapy获取到一些非改网站的链接,比如引用的外站链接等。