Scrapy爬虫框架2-Scrapy进阶使用

62 阅读4分钟

Scrapy中的Item类用于设置传输时的字段,它主要的作用是规范传输的数据格式,当然也可以直接用字典传输。

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class DoubanTopItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

结构化数据

字段通过在类中定义 name = scrapy.Field() 获取数据和存储数据和字典一样。

**使用场景:**当我们获取一些数据,比如电影名称,电影评分,电影作者等数据。为了规范传输的数据格式,我们可以使用Item来创建字段,就和mysql创建字段一样。

class DemoItem(scrapy.Item):
    name = scrapy.Field()
    score = scrapy.Field()
    author = scrapy.Field()

定义字段⾮常简单,赋值⼀个scrapy⽂件中的Field类就⾏

使用实例:(在items文件中要先创建字段)

image.png

from ..items import DoubanTopItem #从上级目录导入..items中的DoubanTopItem模块
item = DoubanTopItem()
item['name'] = '肖申克的救赎'

print(item)
yield item #存储数据需要用到这个

存储数据

  1. 首先需要知道的是我们需要利用pipelines,所以需要在settings里面打开这个功能;
  2. 利用第二步的结构化数据yield返回的item,在pipelines文件中进行操作

案例:爬取 movie.douban.com/top250 中的电影名称和评分数据,全部数据并存储下来

全部代码:

import re
import scrapy
from ..items import DoubanTopItem

class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["movie.douban.com"]
    start_urls = [f'https://movie.douban.com/top250?start={i*25}&filter=' for i in range(10)]

    def parse(self, response):
        data=response.text
        # print(data)

        title=re.findall('class="">\s*<span class="title">(.*?)</span>',data,re.S)  #re.S可以使其匹配到\n
        # print(title)
        # print(len(title))

        rating=re.findall('<span class="rating_num" property="v:average">(.*?)</span>',data)
        # print(rating)
        # print(len(rating))

        #结构化数据
        #法1,使用for循环
        # for title,rating in zip(title,rating):
        #     data={'title':title,'rating':rating}
        #     print(data)
        #     yield data  #返回数据,但不会结束函数
        #法2,使用item进行结构化数据
        item = DoubanTopItem()
        for title,rating in zip(title,rating):
            item['title']=title
            item['rating']=rating
            # print(item)
            yield item
        #存储数据,需要用到pipelines,需要在settings中打开pipelines


        #进行翻页操作
        # 法1:start_urls = [f'https://movie.douban.com/top250?start={i*25}&filter=' for i in range(10)]
        # 法2:start_urls=[]
        # for i in range(10):
        #     start_urls.append(f'https://movie.douban.com/top250?start={i*25}&filter=')

pipelines代码:

# 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
from requests.models import Response #用于一些信息提示

class DoubanTopPipeline:
    # def __init__(self): #与同下代码功能同效
    #     self.file=open('douban_movie.txt','w+',encoding='utf-8')
    def open_spider(self,spider): #爬⾍项⽬启动时只执⾏⼀次,⼀般⽤于数据库连接
        self.file=open('douban_movie.txt','w+',encoding='utf-8')


    def process_item(self, item, spider):
        # self.file.write(str(item) + '\n') #写入的法1
        adapter=ItemAdapter(item)  # 创建ItemAdapter对象
        title = adapter.get('title')
        rating=adapter.get('rating')
        self.file.write(f'电影名称:{title}    电影评分:{rating}\n')
        print('item',item)
        #与爬虫相关的一些信息
        # print(spider.name,spider.allowed_domains)
        return item

    def close_spider(self,spider):
        self.file.close()
        print('爬虫结束关闭文件')

利用scrapy.Request处理翻页数据

scrapy.Request(url,
    callback=None,
    method='GET',
    headers=None,
    body=None,
    cookies=None,
    meta=None,
    encoding='utf-8',
    priority=0,
    dont_filter=False,
    errback=None,
    flags=None)

常⽤参数为:

  1. url: 你要发送请求的URL地址。

  2. callback: 请求完成后将被调⽤的回调函数。当请求的响应返回后,将会调⽤callback函数来处理该

响应。

  1. method: 发送请求的⽅法,默认为’GET’,即发送GET请求。也可以选择使⽤’POST’或者其

他HTTP⽅法。

  1. headers: 请求头信息。可以设置请求头信息来模拟不同的请求。

  2. body: 发送POST请求时的请求体内容。通常在发送POST请求时,会将请求体内容放在这⾥。

  3. cookies: 请求的cookies信息。可以设置cookies来模拟登录状态或其他需要的cookies信息。

  4. meta: ⽤于传递额外的元数据。可以在请求之间传递⼀些额外的数据,供回调函数使⽤。

  5. priority: 请求的优先级,默认为0。可以调整请求的优先级,优先级⾼的请求会先被处理。

  6. dont_filter: 是否进⾏URL去重,默认为False。当设置为True时,会禁⽤对请求URL的去重。

  7. errback: 发⽣错误时的回调函数。当请求出现错误时,将会调⽤errback函数处理异常情况。

  8. flags: 请求的标志位,⽤于传递额外的标志信息。可以根据需要设置不同的标志来处理请求。如

flags={'download_timeout': 10, 'proxy': 'http://my-proxy-server:8888'}
 # download_timeout:⽤于指定下载超时时间,以便针对特定请求设置不同的下载超时时间。
 # proxy:设置请求的代理信息,可以在标志位中指定代理地址,以便对特定请求使⽤代理。

这里对上面的存储数据进行的另一种方法演示:

class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["movie.douban.com"]
    # start_urls = [f'https://movie.douban.com/top250?start={i*25}&filter=' for i in range(10)]
    start_urls =['https://movie.douban.com/top250']
    page=0
    

    def parse(self, response):
        data=response.text
        
        pass
    
        #存储数据
        self.page +=25 #当前对象的page,所以需要self.page
        if self.page <= 225:
            yield scrapy.Request(url=f'https://movie.douban.com/top250?start={self.page}&filter=')

这种方法和通过列表推导式相比:

列表推导式:对于请求是异步获取,也就是说加入列表中的50连接是通过多线程模式来完成的

yield scrapy.Request:需要先获取上一个才能继续完成下一个。一般适用于【比如,请求的下一页参数在上一页的请求体中】