Python-爬虫(六)scrapy快速入门案例-爬取糗事百科

it2023-09-27  79

目录

 

一:安装

二:快速入门

三:开始爬取

 四:存储数据

优化导出数据方式


一:安装

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了。

最新回复(0)