scrapy简介
Scrapy是由Python语言开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取 web站点并从页面中提取结构化的数据,只需要实现少量的代码,就能够快速的抓取。Scrapy使用了Twisted异步网络框架,可以加快我们的下载速度
scrapy框架流程
1 引擎:Hi!Spider, 你要处理哪一个网站?
2 Spider:老大要我处理xxxx.com。
3 引擎:你把第一个需要处理的URL给我吧。
4 Spider:给你,第一个URL是xxxxxxx.com。
5 引擎:Hi!调度器,我这有request请求你帮我排序入队一下。
6 调度器:好的,正在处理你等一下。
7 引擎:Hi!调度器,把你处理好的request请求给我。
8 调度器:给你,这是我处理好的request
9 引擎:Hi!下载器,你按照老大的下载中间件的设置帮我下载一下这个request请求
10 下载器:好的!给你,这是下载好的东西。(如果失败:sorry,这个request下载失败了。然后引擎告诉调度器,这个request下载失败了,你记录一下,我们待会儿再下载)
11 引擎:Hi!Spider,这是下载好的东西,并且已经按照老大的下载中间件处理过了,你自己处理一下(注意!这儿responses默认是交给def parse()这个函数处理的)
12 Spider:(处理完毕数据之后对于需要跟进的URL),Hi!引擎,我这里有两个结果,这个是我需要跟进的URL,还有这个是我获取到的Item数据。
13 引擎:Hi !管道 我这儿有个item你帮我处理一下!调度器!这是需要跟进URL你帮我处理下。然后从第四步开始循环,直到获取完老大需要全部信息。
14 管道调度器:好的,现在就做!
安装
pip install twisted
pip install scrapy
scrapy入门
# 1、创建一个项目(myspider为自定义项目名)
scrapy starproject myspider
# 2、生成一个爬虫,demo为爬虫名
scrapy genspider demo "demo.cn"
# 3、提取数据完善spider 使用xpath,css等
# 4、保存数据pipeline中保存数据
# 5、执行爬虫, name就是爬虫的名字
scrapy crawl name
使用scrapy框架爬番组计划
1、创建项目
用cmd创建项目,锁定d盘,cd找到文件夹
scrapy startproject 项目名称
创建项目后需要修改settings文件的君子协议为False
2、进入项目
cd 项目名称
3、创建爬虫
scrapy genspider 爬虫名字 域名 (爬虫名称不要跟项目名一样,域名建议用截取的网页链接)
创建后的文件在spiders里
5、执行爬虫
scrapy运行不在py文件内,在cmd终端内执行,cmd输入以下执行爬虫文件:
scrapy crawl 爬虫名字
执行后返回的是scrapy日志信息,大部分为没用的信息;修改为仅打印报错的日志信息:
使用cmd运行爬虫
修改User-Agent
获取元素
保存数据两种方法
1、基于终端命令的持久化存储
指令:scrapy crawl 爬虫名字 -o filename(文件名)
只能将parse 方法的返回值存储到本地,支持的文件类型有限(json jsonlines jl csv xml)
items.py 定义字段
import scrapy
# 该模块用于定义字段
class Myspider1Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 定义字段名
title = scrapy.Field()
year = scrapy.Field()
num = scrapy.Field()
执行保存
scrapy crawl fz -o 路径+文件名
2、基于管道的持久化存储
fz.py
import scrapy
from ..items import Myspider1Item
class FzSpider(scrapy.Spider):
# 爬虫文件名
name = 'fz'
# 域名
allowed_domains = ['chii.in']
start_urls = ['https://chii.in/music/browser?sort=rank']
def parse(self, response, **kwargs):
# print(response) # 打印源代码
# 解析数据,scrapy内置xpath解析其他可以导入,返回结果与原本xpath有区别,返回的是一个列表里面是对象
data_list = response.xpath('//*[@id="browserItemList"]/li')
for data in data_list:
# 实例化
item = Myspider1Item()
# extract_first 取当前拿到的第一个值 extract()提取
# 键值对形式进行存储
item['title'] = data.xpath('./div/h3/a/text()').extract_first()
item['year'] = data.xpath('./div/p[1]/text()').extract_first()
item['num'] = data.xpath('./div/p[2]/span/text()').extract_first()
# 将item给管道,yield一次一次存储(不能用return否则只返回最后一个数据)
yield item
items.py 定义字段
import scrapy
# 该模块用于定义字段
class Myspider1Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 定义字段名
title = scrapy.Field()
year = scrapy.Field()
num = scrapy.Field()
pipelines.py 保存数据
from itemadapter import ItemAdapter
# 保存数据
class Myspider1Pipeline:
# 爬虫开始会自动调用此对象
def open_spider(self,spider):
print('爬虫开始')
self.fp = open('./番组.txt','w',encoding='utf-8')
# 专门处理item类型对象,接收到一个item就会调用一次
def process_item(self, item, spider):
# 接收值
title = item['title']
year = item['year']
num = item['num']
# 保存数据
self.fp.write(title+year+num+'\n\n')
return item
def close_spider(self,spider):
print('爬虫结束')
self.fp.close()
豆瓣案例:
1、创建项目
scrapy startproject dbspider
2、创建爬虫
scrapy genspider db douban.com
3、设置settings
修改UA、君子协议18行 USER_AGENT、ROBOTSTXT_OBEY = False
打开管道(取消注释)60+行
ITEM_PIPELINES = { 'dbspider.pipelines.DbspiderPipeline': 300, }
添加运行时只打印报错的日志信息:
LOG_LEVEL = 'ERROR'
db.py
import scrapy
from ..items import DbspiderItem #导入items模块的类
class DbSpider(scrapy.Spider):
name = 'db'
allowed_domains = ['douban.com']
start_urls = ['https://movie.douban.com/top250']
def parse(self, response,**kwargs):
# print(response.text) # 源码
data_list = response.xpath('//*[@id="content"]/div/div[1]/ol/li')
for data in data_list:
item = DbspiderItem()
item['title'] = data.xpath('./div/div[2]/div[1]/a//span[1]/text()').extract_first()
item['message'] = data.xpath('./div/div[2]/div[2]/p[1]/text()').extract_first()
item['score'] = data.xpath('./div/div[2]/div[2]/div/span[2]/text()').extract_first()
item['quote'] = data.xpath('./div/div[2]/div[2]/p[2]/span/text()').extract_first()
yield item #循环用yield
items.py 定义字段
import scrapy
class DbspiderItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 定义字段
title = scrapy.Field()
message = scrapy.Field()
score = scrapy.Field()
quote = scrapy.Field()
pipelines.py 保存数据
import json
from itemadapter import ItemAdapter
class DbspiderPipeline:
def open_spider(self,spider):
print('爬虫开始')
self.db = open('./豆瓣250排行榜.txt','w',encoding='utf-8')
def process_item(self, item, spider):
# 接收值
title = item['title']
message = item['message']
score = item['score']
quote = item['quote']
db_dict={
'电影名':title,
'评分' : score,
'电影金句':quote
}
# 保存数据
db_json = json.dumps(db_dict,ensure_ascii=False,indent=2)
self.db.write(db_json)
return item
def close_spider(self,spider):
print('爬虫结束')
self.db.close()