scrapy数据解析
scrapy持久化存储
-
基于终端指令:
-
指令:scrapy crawl (爬虫文件名) -o (filepath/filename.filetype)
例如:
scrapy crwal qiushi_spider -o ./qiushibaike.json
-
要求:只可以将parse方法的返回值存储到本地文本文件中
-
注意:持久化存储对应的文本文件的类型只可以为:
json
、jsonlines
、jl
、csv
、xml
、marshal
、pickle
-
好处:简洁高效便捷
-
缺点:局限性比较强(数据只可以存储到指定后缀的文本文件中)
-
-
基于管道:
-
编码流程:
-
数据解析:
-
在 [item.py] 文件的Item类中定义相关属性
import scrapy class XxxxItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # pass # 例如定义一个作者属性和内容属性: author = scrapy.Field() content = scrapy.Field()
-
将解析的数据封装存储到item类型的对象
import scrapy from xxx.items import XxxxItem class XxxxSpider(scrapy.Spider): # 爬虫文件名称 name = 'xxx' # 允许域名,如果不在这个域名里边的 url不会进行抓取 allowed_domains = ['www.xxx.com'] # 入口 url,引擎会将入口 url扔到调度器里面 start_urls = ['https://www.xxx.com/'] def parse(self, response): """ 函数说明:做数据解析 :param response: :return: """ pass
-
将item类型的对象提交给管道 [pipelines.py] 进行持久化存储的操作
def parse(self, response): """ 函数说明:做数据解析 :param response: :return: """ 数据解析过程 例:使用xpath解析的作者名称 author item = XxxxItem() item['author'] = author item['content'] = content yield item # 将item提交给管道
-
在管道类的process_item() 方法中,将其接收到的item对象中存储的数据进行持久化存储操作
from itemadapter import ItemAdapter class XxxxPipeline: """ 类说明:专门用来处理 item类型对象 """ def process_item(self, item, spider): """ 函数说明:该方法可以接收爬虫文件提交过来的item对象, 该方法每接收到一个 item就会被调用一次 :param item: :param spider: :return: """ author = item['author'] content = item['content'] 持久化存储操作:保存到文件/数据库 return item
-
在配置文件 [settings.py] 中开启管道,65行左右
ITEM_PIPELINES = { 'xxx.pipelines.XxxxPipeline': 300, # 300表示的是优先级,数值越小优先级越高 }
-
-
好处:通用性强。
-
缺点:编码流程较繁琐。
-
-
面试题:将爬取到的数据一份存储到本地一份存储到数据库,如何实现?
-
存储到本地 [pipelines.py]
from itemadapter import ItemAdapter import pymysql class XxxxPipeline: """ 类说明:专门用来处理 item类型对象 """ fp = None def open_spider(self, spider): """ 函数说明:重写父类的一个方法:该方法只在开始爬虫的时候被调用一次 :param spider: :return: """ print("开始爬虫......") self.fp = open('./xxx.txt', 'w', encoding='utf-8') def process_item(self, item, spider): """ 函数说明:该方法可以接收爬虫文件提交过来的item对象, 该方法每接收到一个 item就会被调用一次 :param item: :param spider: :return: """ author = item['author'] content = item['content'] self.fp.write(author + ": " + content + '\n') return item # 传递给下一个即将被执行的管道类 def close_spider(self, spider): print("爬虫结束......") self.fp.close()
-
存储到mysql数据库 [pipelines.py],这里以mysql数据库为例
class mysqlPipeline(object): """ 类说明:将数据存储到 mysql数据库 """ conn = None # 连接对象 cursor = None # 游标对象 def open_spider(self, spider): """ 函数说明:连接 mysql数据库 :param spider: :return: """ self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='', db='数据库名') def process_item(self, item, spider): # 创建游标对象 self.cursor = self.conn.cursor() author = item['author'] content = item['content'] try: self.cursor.execute('insert into t_qiushi values("%s","%s")' % (author, content)) self.conn.commit() except Exception as e: print(e) self.conn.rollback() return item # 传递给下一个即将被执行的管道类 def close_spider(self, spider): """ 函数说明:关闭数据库连接 :param spider: :return: """ self.cursor.close() self.conn.close()
在配置文件 [settings.py] 中进行配置
ITEM_PIPELINES = { 'xxx.pipelines.XxxxPipeline': 300, 'qiushibaike.pipelines.mysqlPipeline': 301 # 300表示的是优先级,数值越小优先级越高,优先级高的会先执行 }
-
-
思考:这里有两个管道类,那么爬虫文件提交的item类型的对象最终会提交给哪一个管道类呢?
先提交给优先级高的管道类,然后提交给下一个。所以
return item
一定不要忘记。 -
效果展示:
请求传参:
使用场景:如果爬取的数据不在同一张页面中。(深度爬取)