Python爬虫(Scrapy框架)

Python爬虫(Scrapy框架)

1、Scrapy介绍

Scrapy是一个为了爬取网站数据,提取结构化数据二编写的应用框架,其可以应用在包括数据挖掘挖掘,信息处理或存储历史数据等一系列的程序中。

2、安装Scrapy

在pycharm的控制台中需要手动安装scrapy库来进行操作即可。

复制代码
pip install scrapy

3、Scrapy框架讲解

1)Scrapy项目的搭建及运行

一:项目结构的介绍
复制代码
项目名称
	项目名称
		spiders文件夹(存储的是【爬虫文件】)
			_init_.py
			自定义的爬虫文件		【核心功能文件】
		_init_.py
		items.py			定义数据结构文件=> 爬取数据包含哪些
		middlewares.py		中间件 => 一般用于 代理机制
		pipelines.py		管道 => 用于处理下载的数据
		settings.py			配置文件 => 含有 robots协议,User-Agent定义等
二:爬虫文件的结构介绍
python 复制代码
import scrapy

class BaiduSpider(scrapy.Spider):
    name = "baidu"	# 运行爬虫文件时使用的名字【爬虫名称】
    allowed_domains = ["www.baidu.com"] # 爬虫允许访问的域名:若非此url之下的域名会被过滤掉
    start_urls = ["https://www.baidu.com"] # 爬虫的起始url地址

    # 解析数据的回调函数,其中response = requests.get()
    def parse(self, response):
        # 编写内容
三:项目初始化(1)👍
1、创建爬虫项目

注意:项目名字不允许使用数字开头,也不能包含中文

shell 复制代码
# 在终端进行操作:scrapy startproject 项目名称
scrapy startproject scrapy_project
2、创建爬虫文件

步骤一:要在spriders文件夹中去创建爬虫文件

shell 复制代码
# cd 项目名称/项目名称/spiders
cd scrapy_project/scrapy_project/spiders

步骤二:创建爬虫文件

sh 复制代码
# scrapy genspider 爬虫文件名称 要爬取的网页
scrapy genspider baidu https://www.baidu.com

baidu.py爬虫文件内容

python 复制代码
import scrapy

class BaiduSpider(scrapy.Spider):
    # 爬虫名称:运行爬虫时使用的值
    name = "baidu"
    # 允许访问的域名
    allowed_domains = ["www.baidu.com"]
    # 起始的url地址
    start_urls = ["https://www.baidu.com"]

    # response = requests.get()
    def parse(self, response):
        submit = response.xpath('//input[@type="submit"]/@value')
        print(submit)
        print(submit.extract())  # 返回所有符合条件的元素集合
3、运行爬虫代码

步骤一:将settings中的robots协议注释掉

步骤二:在控制台输入命令进行爬取

shell 复制代码
# scrapy crawl 爬虫名称
scrapy crawl baidu

结果展示

复制代码
[<Selector query='//input[@type="submit"]/@value' data='百度一下'>]
['百度一下']
四:response基本方法
python 复制代码
1、content1 = response.text				# 获取的是网页源码(utf-8的字符串数据)
2、content2 = response.body				# 获取的是网页源码(二进制的数据)
3、content3 = response.xpath【推荐】  	 # 可直接xpath方法来解析,返回一个selector列表对象
	content3.extract():返回所有匹配XPath表达式的元素集合,若找到则返回列表,若未找到则返回空列表。
	content3.extract_first():返回第一个匹配Xpath的结果。若找到则返回该元素;若未找到,则返回None。

爬虫文件car.py:爬取"汽车之家"中某一页的汽车的名字

python 复制代码
import scrapy

class CarSpider(scrapy.Spider):
    name = "car"
    allowed_domains = ["www.autohome.com.cn"]
    start_urls = ["https://www.autohome.com.cn/price"]

    def parse(self, response):
        name_list = response.xpath('//div[@class="tw-mt-1 tw-px-4"]//a/text()')
        for i in range(len(name_list)):
            name = name_list[i].extract() # 返回所有符合条件的元素集合
            print(name)
----------------------------------------------
秦L
小米SU7
奥迪A6L
享界S9
秦PLUS
Model Y
帕萨特
迈腾
奔驰E级
理想L6
奥迪Q5L
凯美瑞
宋PLUS新能源
宋L DM-i
问界M7
奥迪A4L
途观L
朗逸
奔驰C级
问界M9
宝马3系
RAV4荣放
汉
林肯Z
宝马5系
海鸥
奔驰GLC
雅阁
宝马X5
航海家
----------------------------------------------

2)Scrapy架构组成

复制代码
(1)引擎:自动运行,无需关注,会自动组织所有的请求对象,分发给下载器
(2)下载器:从引擎处获取请求对象后,请求数据
(3)spiders:spiders类定义了如何爬取某个(或某些)网站和分析网页。
(4)调度器:有自己的调度规则,无需关注
(5)管道(item pipeline):最终处理数据的管道,会预留接口供我们处理数据
补充:当Item在Spiders中被收集后,它将会被传递给Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。每个Item Pipeline组件是实现了简单方法的python类。它们接受到Item并通过它执行一些行为,同时也决定此Item是否通过pipeline,或者被丢弃而不再进行处理。
以下为item pipeline典型应用:
	1. 清理HTML数据
	2. 验证爬取的数据(检验item包含某些字段)
	3. 查重(并丢弃)
	4. 将爬取结构存储到数据库中

3)Scrapy工作原理图

4、Scrapy Shell【了解】

  • 什么是scrapy shell?

scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。其本意是用来测试提取数据的代码,不过您可以将其作为正常的python终端,在上面测任何的python代码。该终端是用来测试Xpath或css表达式,查看他们的工作方式及从爬取的网页中提取的数据。在编写您的spider时,一旦熟悉了scrapy终端后,您会发现其在开发和调试spider时发挥的最大作用。

  • 安装ipython

在pycharm的控制台中需要手动安装ipython库来进行操作即可。

sh 复制代码
pip install ipython

安装ipython后,scrapy终端将使用ipython代替python终端,ipython终端与其他相比更为强大,提供智能的自动补全,高亮输出及其他特性。

  • scrapy shell应用

首先在终端输入命令,如以下命令所示:

shell 复制代码
# scrapy shell url域名
scrapy shell https://www.baidu.com

会自动跳转到ipython页面,如下图:

在以上命令的返回内容中有response,可以直接使用这个response

如下所示:可以调试返回的结果:

  • response相关语法
python 复制代码
(1)response对象:
		response.body	# 返回网页源码(二进制)
		response.text	# 返回网页源码(utf-8)
		response.url	# 返回url域名
		response.status	# 返回状态,正常状态为200
(2)response解析:
		response.xpath()	【推荐】
    		使用xpath路径查询特定元素,返回一个selector列表对象
        response.css()		【不推荐使用,此处就不过多介绍】

5、管道封装(2)👍

必备知识

熟悉yield

基本含义:带有yield的函数不再是一个普通函数,而是一个生成器generator,可用于迭代。yield是一个类似return的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代时,从上一次迭代器遇到的yield后面的代码(下一行)开始执行。

简单理解:yield就是return返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始。yield充当一个传递功能的一个工具。

基本使用

python 复制代码
from scrapy_dangdang.items import ScrapyDangdangItem
            # 构造item对象
            book = ScrapyDangdangItem(src=src,name=name,price=price)

            # 获取一个book就将book交给pipelines
            yield book

1)单管道使用

此处,我们会以小型的完整案例的形式来讲单管道的使用!

案例需求:爬取"当当"网页中的某页的产品名称,价格,图片等信息,并保存在本地【单页数据】。

步骤一:项目初始化
1、创建爬虫项目

注意:项目名字不允许使用数字开头,也不能包含中文

shell 复制代码
# 在终端进行操作:scrapy startproject 项目名称
scrapy startproject scrapy_project
2、创建爬虫文件

步骤一:要在spriders文件夹中去创建爬虫文件

shell 复制代码
# cd 项目名称/项目名称/spiders
cd scrapy_project/scrapy_project/spiders

步骤二:创建爬虫文件

sh 复制代码
# scrapy genspider 爬虫文件名称 要爬取的网页
# 中国古典小说网址:http://category.dangdang.com/cp01.03.32.00.00.00.html
scrapy genspider dang http://category.dangdang.com/cp01.03.32.00.00.00.html
步骤二:定义item文件

通过定义item文件来指定需要获取的信息内容(需要下载哪些内容)

python 复制代码
import scrapy

class ScrapyProjectItem(scrapy.Item):
    # 图片
    src = scrapy.Field()
    # 名字
    name = scrapy.Field()
    # 价格
    price = scrapy.Field()
步骤三:爬取图片、名字、价格
  • 图片爬取

    拿到图片的xpath://ul[@class="bigimg"]//a//img/@src。由于图片具有懒加载的特性,因此对于在处于懒加载中的图片应当获取的是data-original属性。

  • 名字爬取

    拿到标题的xpath://ul[@class="bigimg"]//p[@class="name"]/a/@title

  • 价格爬取

    拿到价格的xpath://ul[@class="bigimg"]//p[@class="price"]//span[@class="search_now_price"]/text()

爬虫文件(dang.py:

python 复制代码
import scrapy
from scrapy_project.items import ScrapyProjectItem

class DangSpider(scrapy.Spider):
    name = "dang"
    allowed_domains = ["category.dangdang.com"]
    start_urls = ["http://category.dangdang.com/cp01.03.32.00.00.00.html"]

    def parse(self, response):
        # src = //ul[@class="bigimg"]/li//a//img/@src
        # name = //ul[@class="bigimg"]/li//p[@class="name"]/a/@title
        # price = //ul[@class="bigimg"]/li//span[@class="search_now_price"]/text()
        front_path = response.xpath('//ul[@class="bigimg"]/li')
        for path in front_path:
            src = path.xpath('.//a//img/@data-original').extract_first()
            # 第一张图片和其他的图片的标签的属性是不一样的
            # 第一张图片的src是可以使用的  其他的图片的地址是data-original
            if src:
                src=src
            else:
                src = path.xpath('.//a//img/@src').extract_first()

            name = path.xpath('.//p[@class="name"]/a/@title').extract_first()
            price = path.xpath('.//span[@class="search_now_price"]/text()').extract_first()

            # yield封装:构造item对象
            book = ScrapyProjectItem(src=src,name=name,price=price)
            # 获取item对象,并将item对象交给pipelines处理(下载等操作)
            yield book
步骤四:管道文件处理(单管道)
  • 在settings.py中开启pipeline

  • 编辑pipeline.py

    python 复制代码
    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
    
    
    # useful for handling different item types with a single interface
    from itemadapter import ItemAdapter
    
    class ScrapyProjectPipeline:
        # 爬虫文件执行之前(初始化操作):打开文件、数据库连接、或者初始化某些资源。
        def open_spider(self, spider):
            self.fp = open('book.json', 'w', encoding='utf-8')
    
        # 爬虫文件执行过程:处理每一个被Spider爬取并返回的Item(数据清洗、验证或存储等操作)
        def process_item(self, item, spider):
            self.fp.write(str(item))
            self.fp.write('\n')
            return item
    
        # 在爬虫文件执行完之后: 文件资源被释放
        def close_spider(self, spider):
            self.fp.close()
步骤五:执行,查看写入的json文件

将settings中的robots协议注释掉:

在控制台输入命令进行爬取:

python 复制代码
# scrapy crawl 爬虫名称
scrapy crawl dang

2)多管道使用

在单管道中只能干一件事情,因此我们可以使用多管道的机制来同时完成多个事情,如:一条管道完成json数据下载,另一条管道完成图片的下载,另一个管道完成视频下载等等。

基本步骤

以上述的小型的完整案例(爬取"当当"网页中的某页产品名称,价格,图片等信息,并保存在本地)进行一定修改,使得其成为一个多管道的小型案例【单页数据】。

(1)pipelines.py定义管道类
python 复制代码
from itemadapter import ItemAdapter
import urllib.request


# 下载基本信息的管道(名字,图片地址,价格)
class ScrapyProjectPipeline:
    # 爬虫文件执行之前(初始化操作):打开文件、数据库连接、或者初始化某些资源。
    def open_spider(self, spider):
        self.fp = open('book.json', 'w', encoding='utf-8')

    # 爬虫文件执行过程:处理每一个被Spider爬取并返回的Item(数据清洗、验证或存储等操作)
    def process_item(self, item, spider):
        self.fp.write(str(item))
        self.fp.write('\n')
        return item

    # 在爬虫文件执行完之后: 文件资源被释放
    def close_spider(self, spider):
        self.fp.close()

# 下载图片的管道【定义管道类】
class DownloadPicPiepline:
    def process_item(self, item, spider):
        # 获取对象值:item.get()
        url = 'http:' + item.get('src')
        # 注意:尽量写完整路径
        filename = 'D:/phase/third_phase/books/' + item.get('name') + '.png'
        # 下载图片
        urllib.request.urlretrieve(url=url,filename=filename)
        return item
(2)settings.py开启管道
恭喜,完成改造!

6、不同(多)页数据获取(3)👍

1)必备知识

熟悉scrapy.Request(GET请求)

含义:scrapy.Request相当于scrpay的get请求

基本格式scrapy.Request(url[,callback=None[,meta='GET']])

scrapy.Request常用参数讲解

复制代码
url:传入的url
callback:指定传入的url交给哪个解析函数去处理
meta:现在不同的解析函数中传递数据,meta默认会携带部分信息,比如下载延迟,请求深度(页码,详情页...)等

2)案例讲解

此处我们会以一个完整的小型案例来讲解不同(多)页数据获取。

案例需求:爬取电影天堂不同页面的数据

1、效果
  • 获取电影天堂,【列表页面】的电影名:
  • 然后点击进入电影【详情页面】,再从第二页获取到详情中的图片:
2、具体代码
步骤一:项目初始化
1、创建爬虫项目

注意:项目名字不允许使用数字开头,也不能包含中文

shell 复制代码
# 在终端进行操作:scrapy startproject 项目名称
scrapy startproject scrapy_project
2、创建爬虫文件

步骤一:要在spriders文件夹中去创建爬虫文件

shell 复制代码
# cd 项目名称/项目名称/spiders
cd scrapy_project/scrapy_project/spiders

步骤二:创建爬虫文件

sh 复制代码
# scrapy genspider 爬虫文件名称 要爬取的网页
# 电影天堂:https://www.dygod.net/html/gndy/china/index.html
scrapy genspider mv https://www.dygod.net/html/gndy/china/index.html
步骤二:定义item文件

通过定义item文件来指定需要获取的信息内容(需要下载哪些内容)

python 复制代码
import scrapy

class ScrapyProjectItem(scrapy.Item):
    # 图片
    src = scrapy.Field()
    # 名字
    name = scrapy.Field()
步骤三:爬取列表页,详情页数据

爬虫文件(mv.py【核心代码】:

python 复制代码
import scrapy
from scrapy_project.items import ScrapyProjectItem

class MvSpider(scrapy.Spider):
    name = "mv"
    allowed_domains = ["www.dygod.net"]
    start_urls = ["https://www.dygod.net/html/gndy/china/index.html"]

    # 列表页
    def parse(self, response):
        # 要列表页中的名字 和 详情页中的图片
        a_list = response.xpath('//div[@class="co_content8"]//td[2]//a[2]')

        for a in a_list:
            # 获取列表页的name 和 要点击的链接
            name = a.xpath('./text()').extract_first()
            href = a.xpath('./@href').extract_first()

            # 详情页的地址是
            url = 'https://www.dygod.net' + href

            # 对详情页的链接发起访问 并将name参数传入,交给parse_second进行处理
            yield scrapy.Request(url=url, callback=self.parse_second, meta={'name': name})

    # 详情页
    def parse_second(self, response):
        src = response.xpath('//div[@id="Zoom"]//img/@src').extract_first()
        # 接受到请求的那个meta参数的值
        name = response.meta['name']

        # 将数据封装至item并传给pipeline进行最终处理
        movie = ScrapyProjectItem(src=src, name=name)
        yield movie
步骤四:管道文件处理
  • 在settings.py中开启pipeline

  • 编辑pipeline.py

    python 复制代码
    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
    
    
    # useful for handling different item types with a single interface
    from itemadapter import ItemAdapter
    
    class ScrapyProjectPipeline:
        # 爬虫文件执行之前(初始化操作):打开文件、数据库连接、或者初始化某些资源。
        def open_spider(self, spider):
            self.fp = open('movies.json', 'w', encoding='utf-8')
    
        # 爬虫文件执行过程:处理每一个被Spider爬取并返回的Item(数据清洗、验证或存储等操作)
        def process_item(self, item, spider):
            self.fp.write(str(item))
            self.fp.write('\n')
            return item
    
        # 在爬虫文件执行完之后: 文件资源被释放
        def close_spider(self, spider):
            self.fp.close()
步骤五:执行,查看写入的csv文件

将settings中的robots协议注释掉:

在控制台输入命令进行爬取:

python 复制代码
# scrapy crawl 爬虫名称
scrapy crawl mv

7、日志信息和日志等级

复制代码
(1)日志级别:
		CRITICAL: 严重错误
		ERROR: 一般错误
		WARNING: 警告
		INFO: 一般信息
		DEBUG: 调试信息
	默认的日志级别是DEBUG,出现了DEBUG后DEBUG以上级别日志,这些日志信息都会别打印出来

(2)settings.py文件设置:
	默认的日志级别是DEBUG,会显示上面的所有信息。
	修改级别配置:
		LOG_FILE: 将屏幕显示的信息全部记录在文件中,屏幕不显示,注意【文件后缀名必须为.log】 👍
		LOG_LEVEL: 设置文件显示的级别,即:显示哪些,不显示哪些。

在settings.py文件中手动添加:

8、Scrapy的post请求

1)熟悉scrapy.FormRequest(POST请求)
复制代码
scrapy.FormRequest(url=url,formdata=data,callback=self.parse_second,headers=headers)
参数讲解:	
	url:要发送的post地址
	formdata:post所携带的数据,这是一个字典
	callback:回调函数
	headers:定制请求头信息
2)案例讲解

此处以百度翻译为例讲述POST请求。首先,在Network中寻找完整的POST发送信息(eye)的文件,如下图所示

然后,对Headers中的url路径进行爬取操作

主要的代码部分【爬虫文件fanyi.py:发送带有请求参数的POST请求

python 复制代码
import json
import scrapy

class FanyiSpider(scrapy.Spider):
    name = "fanyi"
    allowed_domains = ["fanyi.baidu.com"]

    # post请求【固定写法】
    def start_requests(self):
        url = 'https://fanyi.baidu.com/sug'
        # 参数
        data = {
            'kw': 'eye'
        }
        # scrapy中post请求用FormRequest表示
        yield scrapy.FormRequest(url=url,formdata=data,callback=self.parse_second)

    # 接受post请求返回的数据并进行处理
    def parse_second(self,response):
        # 获取网页内容
        content = response.text
        obj = json.loads(content)
        print(obj)
相关推荐
modelmd2 小时前
【递归算法】汉诺塔
python·算法
2501_941652772 小时前
基于YOLO12-A2C2f-FRFN的电缆连接器类型识别与定位
python
喵手2 小时前
Python爬虫实战:采集双色球(SSQ)历史开奖数据(期号、红球、蓝球、开奖日期)等信息,并进行结构化CSV存储(Requests + Pandas)!
爬虫·python·爬虫实战·零基础python爬虫教学·双色球历史开奖数据·期号红球篮球开奖日期等·结构化csv存储
2401_838472512 小时前
C++中的装饰器模式实战
开发语言·c++·算法
沐知全栈开发2 小时前
PHP 数组
开发语言
雨季6662 小时前
Flutter 三端应用实战:OpenHarmony “心流之泉”——在碎片洪流中,为你筑一眼专注的清泉
开发语言·前端·flutter·交互
氵文大师2 小时前
PyTorch 性能分析实战:像手术刀一样精准控制 Nsys Timeline(附自定义颜色教程)
人工智能·pytorch·python
梦幻精灵_cq2 小时前
正文标题党——正文标题也需要精致
python
YMWM_2 小时前
python3中类的__call__()方法介绍
开发语言·python