【Scrapy】Scrapy教程5——第一个Scrapy项目


通过前几节的学习,我们已经了解了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 # 初始化文件,和python的__init__.py文件一样,用于将目录标记为包和包的初始化
│ │
│ ├─spiders # 爬虫代码文件夹
│ │ │ shouye.py # 刚刚创建的爬虫代码文件,用来编写爬虫规则
│ │ │ __init__.py # 初始化文件

第一个爬虫

知道了Scrapy的目录结构,我们可以动手开始做我们的第一个爬虫了,从目录结构中能看到,爬虫规则是写在spiders文件夹下的爬虫代码文件中,刚创建的第一个爬虫代码文件叫shouye.py,我们打开这个文件,可以看到以下内容,同样我为代码加上了注释,一定要仔细看注释,不然后面可能有些内容会不清楚。

import scrapy  # 导入scrapy包

# 爬虫类,类名一般是name+Spider,必须是Spider的子类,即需要继承Spider才能被Scrapy识别
class ShouyeSpider(scrapy.Spider):
    # 爬虫名称name,一个项目中名称需要保持唯一
    name = "shouye"
    # allowed_domains允许访问的域名列表,默认开启,只允许爬取该列表下的页面,可在settings.py的中间件中部分关闭
    allowed_domains = ["www.jayhgq.cn"]
    # 第一个请求的地址默认从start_urls中获取
    start_urls = ["https://www.jayhgq.cn"]

# 默认回调函数parse,用来处理请求的响应response,可以在这里进行数据提取
    def parse(self, response):
        pass

以上是用scrapy的genspider命令自动生成的,但是这样我们执行什么都存储不下来,我们来做下简单的改动,如下

# 导入pathlib来处理文件路径等问题
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' # 设置文件名filename,将爬取的内容存储
        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文件,如果用浏览器打开只是一些文字和链接,非常难看。

upload successful

必要说明

如果你教程看到这,恭喜你,已经可以完成一次爬虫了。
大家可能会有疑问,爬虫这么简单吗?笔者想说,就是这么简单,但是,还有但是,爬虫并不仅如此,还有很多内容,比如如何提取数据、如何持久化数据、如何添加相关请求参数、如何设置中间件等等。
在进行后面的讲解前,我们先对上面的代码进行下补充说明。

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"
# 修改headers的示例
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)

# 修改POST请求的示例
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获取到一些非改网站的链接,比如引用的外站链接等。


文章作者: Admin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Admin !
  目录