scrapy框架之基础
一、安装scrapy
安装失败看博客>>>scrapy安装失败解决方案
pip install wheel
pip install twisted
pip install pywin32
pip install scrapy
二、创建爬虫项目
scrapy startproject firstPro # firstPro表示项目名称
项目目录结构
cmd命令行输入 D:\爬虫项目\first>tree /f
└─first │ items.py │ middlewares.py │ pipelines.py │ settings.py │ __init__.py │ ├─spiders │ │ jingdong.py │ │ __init__.py │ │ │ └─__pycache__ │ jingdong.cpython-36.pyc │ __init__.cpython-36.pyc │ └─__pycache__ items.cpython-36.pyc pipelines.cpython-36.pyc settings.cpython-36.pyc __init__.cpython-36.pyc
scrapy.cfg # scrapy部署时的配置文件 taobao # 项目的模块,需要从这里引入 __init__.py items.py # 定义爬取的数据结构 middlewares.py # 定义爬取时的中间件 pipelines.py # 定义数据管道 settings.py # 配置文件 spiders # 放置爬虫的文件夹 __init__
三、创建爬虫
# 在spiders文件夹中创建一个py文件用于网页抓取内容并解析结果 - cmd命令行创建 - D:\爬虫项目\taobao\taobao\spiders>scrapy genspider jingdong www.xxx.com - jingdong为蜘蛛名称 www.xxx.com为域名 # 创建的jingdong.py import scrapy class JingdongSpider(scrapy.Spider): name = 'jingdong' # 项目唯一的名字,用来区分不同的spider allowed_domains = ['www.xxx.com'] # 允许爬取的域名 start_urls = ['http://www.xxx.com/'] # spider启动时抓取的url列表 # 负责解析/提取/start_urls里面请求完的响应数据 def parse(self, response): pass
定义item字段
在解析数据之前我们要在items文件中定义我们要解析的字段,因为我们解析完的数据需要提交到管道,而管道只接收item对象
import scrapy class FirstItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() name = scrapy.Field()
数据爬取并解析
import scrapy from first.items import FirstItem # 导入items中的FirstItem类 class JingdongSpider(scrapy.Spider): name = 'jingdong' allowed_domains = ['www.xxx.com'] start_urls = ['https://www.cnblogs.com/songzhixue/p/10717975.html'] # 管道存储 函数名parse也是不可以更改的 def parse(self, response): tetle = response.xpath('//*[@id="cnblogs_post_body"]/ul/li/a/text()').extract() for name in tetle: # 实例化一个item对象 item = FirstItem() # 将解析到的数据全部封装到item对象中 item["name"] = name yield item # 将item提交给管道
这里我们使用了extrct
tetle = response.xpath('//*[@id="cnblogs_post_body"]/ul/li/a/text()') # xpath提取完是一个Selector对象 <Selector xpath='//*[@id="cnblogs_post_body"]/ul/li/a/text()' data='基础【一】基础数据类型'> # 提取data数据需要加上.extract() tetle = response.xpath('//*[@id="cnblogs_post_body"]/ul/li/a/text()').extract() #返回值为列表 # extract_first() #取列表中的第一项 等于extract()[0] # 如果我们xpath写错或者xpath拿不到值时我们调用了extract_first() 则返回值为None
四、数据持久化
管道只接收item对象,所以我们必须在items中给数据定义字段,并将解到的数据写入item对象中
# 基于管道的数据持久化 # 处理jingdong爬虫数据的管道 class FirstPipeline1(object): fp = None # 打开文件 重写父类的方法 只会执行一次 def open_spider(self,spider): print("开始爬虫------") self.fp = open("./spider.txt","w",encoding="utf-8") # 可以定义任意文件的后缀 def process_item(self, item, spider): name = item["name"] self.fp.write(name+"\n") return item def close_spider(self,spider): print("结束爬虫------") self.fp.close()
持久化流程
items.py :数据结构模板文件,定义数据属性
pipelines.py :管道文件,接收数据(items)进行持久化操作
- 持久化存储
- 基于终端指令:
- 前提:只可以将parse方法的返回值进行本地文件的持久化存储
- 指令:scrapy crawl spiderName -o filePath
- 基于管道:
1.数据解析
2.需要在item类中定义相关的属性(存储解析到的数据)
3.将解析到的数据存储或者封装到一个item类型的对象中
4.将item对象提交到管道中
5.在管道中需要接收item,且将item对象中的数据进行任意形式的持久化操作
6.在配置文件中开启管道
终端持久化不需要开启管道,在爬虫文件中将解析后的数据返回即可
class JingdongSpider(scrapy.Spider): name = 'jingdong' allowed_domains = ['www.xxx.com'] start_urls = ['https://www.cnblogs.com/songzhixue/p/10717975.html'] # 终端数据持久化存储,只可以存储到磁盘 def parse(self, response): tetle = response.xpath('//*[@id="cnblogs_post_body"]/ul/li/a/text()').extract() all_list = [] for name in tetle: dic = { "name":name } all_list.append(dic) return all_list # 在终端输入指令即可本地化存储 D:\爬虫项目\first>scrapy crawl jingdong -o jingdong.csv # 基于终端指令进行数据持久化存储保存的格式 'json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle'
五、打开管道
settings常用配置
# 请求头配置 USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36' # 配置文件中开启管道 ITEM_PIPELINES = { # 300表示优先级,(数值越小优先级越高) 'first.pipelines.FirstPipeline': 300, } # 设置日志等级 LOG_LEVEL = 'WARNING' # ROBOTS协议配置 ROBOTSTXT_OBEY = False # 是否处理cookie COOKIES_ENABLED = False
scrapy管道的细节处理 - 数据的爬取和持久化存储,将同一组数据分别存储到不同的平台 - 一个管道类负责将数据存储到某一个载体或者平台中 - 爬虫文件提交的item只会提交给第一个被执行的管道类 - 在管道类的process_item中的return item表示的含义就是将当前管道类接收到的item传递给下一个即将被执行的管道类 - 注意:爬虫类和管道类进行数据交互的形式 - yild item:只可以交互item类型的对象 - spider参数:可以交互任意形式的数据
- 一个爬虫项目可以有多个spider,每个爬虫的数据持久化方式可能不同,这时我们就需要用到多个管道来处理不同爬虫的数据存储 # 处理jingdong爬虫数据的管道 class FirstPipeline1(object): # 可以将item类型对象中存储的数据进行持久化存储 def process_item(self, item, spider): # spider就是爬虫对象,通过点的方式调用jingdong爬虫类中的属性,判断是哪个爬虫 if spider.name == "jingdong": # item就是经过spider处理完传过来的数据 print(item["name"]) # 取值必须用中括号 return item # 将item传给下一个管道 # 处理taobao爬虫数据的管道 class FirstPipeline2(object): def process_item(self, item, spider): # spider就是爬虫对象 if spider.name == "taobao": print(item["name"]) return item # sttings配置 ITEM_PIPELINES = { # 300表示优先级,(数值越小优先级越高) 'first.pipelines.FirstPipeline1': 300, 'first.pipelines.FirstPipeline2': 301, } 哪个管道的优先级高就先运行哪个管道
六、启动项目
# 进入项目文件夹下启动 # 在cmd执行 scrapy crawl 爬虫名字 scrapy crawl jingdong --nolog # 不打印log日志