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文件中要先创建字段)
from ..items import DoubanTopItem #从上级目录导入..items中的DoubanTopItem模块
item = DoubanTopItem()
item['name'] = '肖申克的救赎'
print(item)
yield item #存储数据需要用到这个
存储数据
- 首先需要知道的是我们需要利用pipelines,所以需要在settings里面打开这个功能;
- 利用第二步的结构化数据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)
常⽤参数为:
-
url: 你要发送请求的URL地址。
-
callback: 请求完成后将被调⽤的回调函数。当请求的响应返回后,将会调⽤callback函数来处理该
响应。
- method: 发送请求的⽅法,默认为’GET’,即发送GET请求。也可以选择使⽤’POST’或者其
他HTTP⽅法。
-
headers: 请求头信息。可以设置请求头信息来模拟不同的请求。
-
body: 发送POST请求时的请求体内容。通常在发送POST请求时,会将请求体内容放在这⾥。
-
cookies: 请求的cookies信息。可以设置cookies来模拟登录状态或其他需要的cookies信息。
-
meta: ⽤于传递额外的元数据。可以在请求之间传递⼀些额外的数据,供回调函数使⽤。
-
priority: 请求的优先级,默认为0。可以调整请求的优先级,优先级⾼的请求会先被处理。
-
dont_filter: 是否进⾏URL去重,默认为False。当设置为True时,会禁⽤对请求URL的去重。
-
errback: 发⽣错误时的回调函数。当请求出现错误时,将会调⽤errback函数处理异常情况。
-
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
:需要先获取上一个才能继续完成下一个。一般适用于【比如,请求的下一页参数在上一页的请求体中】