目录
一:安装
window环境通过命令行安装: pip install scrapy
在winodw下使用这个框架还要安装一个它依赖的包,不然运行的时候会报错: pip install pypiwin32
二:快速入门
安装成功之后可以通过:scrapy 命令查看相关命令。
我们使用startproject命令创建一个新项目。: scrapy startproject first_start
用pycharm打开这个项目看下生成的目录。
项目创建好之后,我们开始创建一个爬虫。创建一个爬虫需要用到一个命令: genspider
进入我们项目的spiders目录下用命令行创建: scrapy genspider qiushibaike "qiushibaike.com"
qiushibaike ---爬虫的名字 qiushibaike.com---爬虫需要的域名
自动创建的内容:
开始之前先设置一些东西。
1)settings.py中设置:
我们解释下自动生成的py文件中的一些数据的作用。
我们运行爬虫也是要命令行,进入到spiders目录下面执行:scrapy crawl qiushibaike--自定义爬虫的名字
我们主要使用response对象来过滤xpath。我们看下
返回的是个SelectorList类型。它是可以遍历,并且可以继续使用xpath函数进行提取的。
但是使用命令行执行爬虫不是很方便,我们可以使用python文件来启动。在项目的根目录下创建一个新文件,在里面使用:
from scrapy import cmdline
#传入我们的启动命令
cmdline.execute("scrapy crawl qiushibaike".split())
后面我们可以直接运行这个文件就可以启动爬虫程序了。
三:开始爬取
我们看到页面内容:
可以根据class='recmd-right'来定位
我们来得到作者:
分析页面,可以知道,在上面我们得到div之后,在div下面的span标签内存着作者,所以通过如下方式获取。
def parse(self, response):
# response是一个HtmlResponse对象,可以用它获取返回的内容response.text,使用xpath获取内容response.xpath("..")
print("*************************")
responseContent = response.xpath("//div[@class='recmd-right']")
for i in responseContent:
print(i.xpath(".//span[@class='recmd-name']/text()").get())
print("******************************")
四:存储数据
我们现在试着把爬取到的内容存储到json文件。scrapy中爬取和存储是分开两个模块处理。我们的爬取程序是在spiders下面,但是对爬取下来的数据处理是在pipelines中的。
首页我们需要把在spiders中把爬取的数据yield出去,然后在pipelines中接收处理。
spiders中:
注意我们这里使用yield,也可以把所有的数据都准备好之后直接return出来。
def parse(self, response):
# response是一个HtmlResponse对象,可以用它获取返回的内容response.text,使用xpath获取内容response.xpath("..")
print("*************************")
responseContent = response.xpath("//div[@class='recmd-right']")
for i in responseContent:
author=i.xpath(".//span[@class='recmd-name']/text()").get()
title=i.xpath(".//a[@class='recmd-content']/text()").get()
#把数据转为字典
data={"author": author,"title":title}
#把数据转给pipelines,需要使用 yield, 代表把数据转给底层框架,然后框架会转给pipelines.py文件中
yield data
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
import json
class FirstProjectPipeline:
#初始化函数,打开一个文件,也可以在open_spider方法中
def __init__(self):
self.fp=open("data.json","w",encoding="utf-8")
#爬虫程序启动的时候执行这个函数
def open_spider(self,spider):
print('爬虫开始')
#我们在spiders中yield 的数据 会传递给 item这个参数,然后执行process_item中的逻辑
def process_item(self, item, spider):
#在spider中yield是个字典型数据 我们转成json dumps不需要文件参数,ensure_ascii关闭掉可以存储中文
item_json=json.dumps(item,ensure_ascii=False)
self.fp.write(item_json+'\n')
return item
#这个爬虫程序执行完成之后执行的方法
def close_spider(self,spider):
print('爬虫结束')
但是要让pipelines生效配置文件中还要有个内容放开注释:
默认是注释掉的。
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
#key是类路径,value是优先级,越小优先级越高
'first_project.pipelines.FirstProjectPipeline': 300,
}
运行程序看到出来的json文件:
上面我们是在爬虫程序里返回是个字典型数据给pipelines的,但是在scrapy中有更专业的写法,就是用包装类。
首先我们要在items.py中定义包装数据的类,items.py中就是专门放这些包装类的。
item.py:
import scrapy
class FirstProjectItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
author=scrapy.Field()
title=scrapy.Field()
在spiders中引入使用:
注意引入的方式,从我们的项目名下的item引入。
from first_project.items import FirstProjectItem
def parse(self, response):
# response是一个HtmlResponse对象,可以用它获取返回的内容response.text,使用xpath获取内容response.xpath("..")
print("*************************")
responseContent = response.xpath("//div[@class='recmd-right']")
for i in responseContent:
author=i.xpath(".//span[@class='recmd-name']/text()").get()
title=i.xpath(".//a[@class='recmd-content']/text()").get()
#把数据转为字典
# data={"author": author,"title":title}
data=FirstProjectItem(author=author,title=title)
#把数据转给pipelines,需要使用 yield, 代表把数据转给底层框架,然后框架会转给pipelines.py文件中
yield data
pipelines中我们要稍微改动下,因为传入的是个对象,我们存入json文件的时候,转为字典。
def process_item(self, item, spider):
#在spider中yield是个字典型数据 我们转成json dumps不需要文件参数,ensure_ascii关闭掉可以存储中文
item_json=json.dumps(dict(item),ensure_ascii=False)
self.fp.write(item_json+'\n')
return item
这样就可以继续使用了。
优化导出数据方式
上面我们使用Json来导出爬取的数据,还要转换为字典型,不太方便,其实scrapy中给我们提供的有导出器可以使用更方便数据导出。
pipelines中的代码改为如下内容:
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
#引入Json导出器
from scrapy.exporters import JsonItemExporter
class FirstProjectPipeline:
#初始化函数,打开一个文件,也可以在open_spider方法中
def __init__(self):
#同样时打开一个文件,但是这里要以wb字节的形式打开,因为导出器是处理字节数据的而且不用指定编码格式
self.fp=open("data.json","wb")
#传入上面定义的文件对象,禁用ascii码 使用utf-8编码
self.export=JsonItemExporter(self.fp,ensure_ascii=False,encoding='utf-8')
#开启导出
self.export.start_exporting()
#爬虫程序启动的时候执行这个函数
def open_spider(self,spider):
print('爬虫开始')
#我们在spiders中yield 的数据 会传递给 item这个参数,然后执行process_item中的逻辑
def process_item(self, item, spider):
#爬虫哪里得到的item可以直接使用,不用转换为字典
self.export.export_item(item)
return item
#这个爬虫程序执行完成之后执行的方法
def close_spider(self,spider):
# 完成导入之后关闭导出器,才会真正的写入文件中取,存入文件的内容为一个列表,列表里是一个个字典
self.export.finish_exporting()
print('爬虫结束')
内容:
这种方式是会把爬取到的内容都先在内存中存储一个列表中,列表中存储爬取的item,最后在写入文件中,如果爬取的内容很多,会很占内存。
还有一种导出方式,按行来导出,而不是占用内存最后再导出。
#引入Json导出器
from scrapy.exporters import JsonLinesItemExporter
class FirstProjectPipeline:
#初始化函数,打开一个文件,也可以在open_spider方法中
def __init__(self):
#同样时打开一个文件,但是这里要以wb字节的形式打开,因为导出器是处理字节数据的而且不用指定编码格式
self.fp=open("data.json","wb")
#传入上面定义的文件对象,禁用ascii码 使用utf-8编码
self.export=JsonLinesItemExporter(self.fp,ensure_ascii=False,encoding='utf-8')
#爬虫程序启动的时候执行这个函数
def open_spider(self,spider):
print('爬虫开始')
#我们在spiders中yield 的数据 会传递给 item这个参数,然后执行process_item中的逻辑
def process_item(self, item, spider):
#爬虫哪里得到的item可以直接使用,不用转换为字典
self.export.export_item(item)
return item
#这个爬虫程序执行完成之后执行的方法
def close_spider(self,spider):
print('爬虫结束')
导入内容:
一个字典占用一行,而不是一个列表了。数量大的时候可以使用这个方式,而且不用start,和finish了。