オリジナル:http://106.13.73.98/__/138/
永続ストレージ指示端末に基づいて、
前提条件:ファイルクローラていることを確認し、解析プロセスの反復が値データ型(通常はリスト/ dictのを)返すことがあります。
戻り値は、永続ストレージのための命令の形で端末によって指定されたファイル形式に書き込むことができます。
永続ストレージに次のコマンドを実行します。
scrapy crawl 应用名称 -o xx.文件格式
これは、ファイル形式をサポートしている:'JSON'、 'jsonlines'、 'JL'、 'CSV'、 'XML'、 '元帥'、 '漬物'
永続ストレージのパイプラインに基づいて、
Scrapyフレームワークは、効率的で便利な永続的な操作機能を提供してくれ、我々は直接使用することができます。
使用する前に、これらの2つのファイルを認識してみましょう:
- items.py:データ構造のテンプレートファイルは、データ属性を定義するために使用されます。
- pipelines.py:コンジットファイルは、長期的な操作のために、データ(項目)を受信しました。
---------------------------↓の
永続化プロセス:
- アプリケーションファイルのデータをクロールした後、にカプセル化されたデータ項目は、オブジェクト。
- 使用利回りキーワード項目ターゲットに提出パイプライン永続化のためには、パイプラインを運営しています。
- クラス管におけるファイルprocess_itemの上クローラの送信を受信する方法アイテムオブジェクト、
及び、コード永続ストレージ書き込み項目永続ストアに格納されたデータオブジェクトを。
注意:
- でsettings.py辞書内のオープンパイプライン構成プロファイル:ITEM_PIPELINES
- でitems.py良いフィールドの定義永続的なデータ構造テンプレートファイルであることを
---------------------------↑
例
登るには、以下の記事とあなたのCSDNのブログのURL、および永続ストレージの間のすべての対応をとります。
最初のステップは、のは、アプリケーションファイル書いてみましょうblog.pyを:import scrapy from Test.items import TestItem class BlogSpider(scrapy.Spider): name = 'blog' # 应用名称 start_urls = ['https://blog.csdn.net/qq_41964425/article/list/1'] # 起始url page = 1 # 用于计算页码数 max_page = 7 # 你的CSDN博客一共有多少页博文 url = 'https://blog.csdn.net/qq_41964425/article/list/%d' # 用于定位页码的url def parse(self, response): """ 访问起始url页面并获取结果后的回调函数 一般情况下,你写了多少个起始url,此方法就会被调用多少次 :param response: 向起始URL发送请求后,获取的响应对象 :return: 此方法的返回值必须为 可迭代对象(通常为list/dict) 或 None """ # 定位到当期页面中所有博文的链接(a标签) a_list = response.xpath('//div[@class="article-list"]/div/h4/a') # type: list # 每个人的博客,每一页的都有这篇文章,你打开网页源码看看就知道了 a_list.pop(0) # 帝都的凛冬 https://blog.csdn.net/yoyo_liyy/article/details/82762601 # 开始解析处理博客数据 for a in a_list: # 准备一个item对象 item = TestItem() # 保存数据 item['title'] = a.xpath('.//text()')[-1].extract().strip() # 获取文章标题 item['url'] = a.xpath('.//@href').extract_first() # 获取文章url # 下面将解析到的数据存储到item对象中 # 最后,将itme对象提交给管道进行持久化存储 yield item # 开始爬取所有页面 if self.page < self.max_page: self.page += 1 current_page = format(self.url % self.page) # 当前的要爬取的url页面 # 手动发送请求 yield scrapy.Request(url=current_page, callback=self.parse) # callback用于指定回调函数,即指定解析的方法 # 1.如果页面内容与起始url的内容一致,可使用同一个解析方法(self.parse) # 2.如果页面的内容不一致,需手动创建新的解析方法,可见下面 def dem(self, response): """ 2.如果页面的内容不一致,需手动创建新的解析方法 注意:解析方法必须接收response对象 """ pass
データ構造テンプレートファイルの2番目のステップitems.py保存する準備ができてフィールドに:
import scrapy class TestItem(scrapy.Item): # define the fields for your item here like: title = scrapy.Field() # 文章标题 url = scrapy.Field() # 文章url
パイプラインファイルにおける第三段階pipelines.pyのロジックでの持続的な書き込み:
class TestPipeline(object): def process_item(self, item, spider): """应用文件每提交一次item,该方法就会被调用一次""" # 保存数据到文件 self.fp.write(item['title'] + '\t' + item['url'] + '\n') # 你一定要注意: # 此方法一定要返回itme对象,用于传递给后面的(优先级低的)管道类中的此方法 # 关于优先级的高低,可在settings.py文件中的ITEM_PIPELINES字典中定义 return item # 重写父类方法,用于打开文件 def open_spider(self, spider): """此方法在运行应用时被执行,注意:只会被执行一次""" print('开始爬取') self.fp = open('text.txt', 'w', encoding='utf-8') # 重写父类方法,用于关闭文件 def close_spider(self, spider): """此方法结束应用时被执行,注意:只会被执行一次""" print('爬取结束') self.fp.close()
設定ファイルの4番目の手順settings.py次の設定項目を開くには:
# 伪装请求载体身份(User-Agent) USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' # 是否遵守robots协议 ROBOTSTXT_OBEY = False # 开启管道 ITEM_PIPELINES = { 'Test.pipelines.TestPipeline': 300, # 300表示的是优先级,数值越小优先级越高,优先级高的先执行 # 自定义的管道类添加到此字典时才会被调用 }
第五ステップ、入力ターミナルでコマンドを実行します。scrapyクロールブログは、実装を成功した後、私たちは、見たいファイルを開きます。
どのように、これを以下のようにされていません。
ハッハッハ。
我々は、ファイルにデータを永続化することができない、慌てないでください、あなたはまた、データベースにデータを永続化することができます(たとえば、次のMySQL、Redisの)。
---------------------------------------↓
MySQLへ永続ストレージ# pipelines.py文件 import pymysql # 自定义管道类,用于将数据写入MySQL # 注意了: # 自定义的管道类需要在settings.py文件中的ITEM_PIPELINES字典中注册后才会被调用 # 而调用的顺序取决于注册时指定的优先级 class TestPipeLineByMySQL(object): # 重写父类方法,用于建立MySQL链接,并创建一个游标 def open_spider(self, spider): """此方法在运行应用时被执行,注意:只会被执行一次""" self.conn = pymysql.connect( host='localhost', port=3306, user='zyk', password='user@zyk', db='blog', # 指定你要使用的数据库 charset='utf8', # 指定数据库的编码 ) # 建立MySQL链接 self.cursor = self.conn.cursor() # 创建游标 # 本人实测:这里并发使用同一个游标没有出现问题 def process_item(self, item, spider): sql = 'insert into info(title, url) values (%s, %s)' # 要执行的sql语句 # 开始执行事务 try: self.cursor.execute(sql, (item['title'], item['url'])) # 增 self.conn.commit() # 提交 except Exception as e: print(e) self.conn.rollback() # 回滚 return item # 你一定要注意: # 此方法一定要返回itme对象,用于传递给后面的(优先级低的)管道类中的此方法 # 关于优先级的高低,可在settings.py文件中的ITEM_PIPELINES字典中定义 # 重写父类方法,用于关闭MySQL链接 def close_spider(self, spider): """此方法在结束应用时被执行,注意:只会被执行一次""" self.cursor.close() self.conn.close()
書き込み後に設定ファイルを忘れないでくださいsettings.pyは、このパイプラインのクラスを追加します。
ITEM_PIPELINES = { 'Test.pipelines.TestPipeline': 300, # 300表示的是优先级,数值越小优先级越高,优先级高的先执行 'Test.pipelines.TestPipeLineByMySQL': 400, # 自定义的管道类添加到此字典时才会被调用 }
---------------------------------------↓
のRedisの永続ストレージ# pipelines.py文件 import redis import json # 自定义管道类,用于将数据写入Redis # 注意了: # 自定义的管道类需要在settings.py文件中的ITEM_PIPELINES字典中注册后才会被调用 # 而调用的顺序取决于注册时指定的优先级 class TestPipelineByRedis(object): # 重写父类方法,用于创建Redis连接实例 def open_spider(self, spider): """此方法在运行应用时被执行,注意:只会被执行一次""" # 创建Redis连接实例 self.conn = redis.Redis(host='localhost', port=6379, password='', decode_responses=True, db=15) # decode_responses=True 写入的键值对中的value为字符串类型,否则为字节类型 # db=15 表示使用第15个数据库 def process_item(self, item, spider): dct = { 'title': item['title'], 'url': item['url'] } # 将数据持久化至Redis self.conn.lpush('blog_info', json.dumps(dct, ensure_ascii=False)) # ensure_ascii=False 这样可使取数据时显示的为中文 return item # 你一定要注意: # 此方法一定要返回itme对象,用于传递给后面的(优先级低的)管道类中的此方法 # 关于优先级的高低,可在settings.py文件中的ITEM_PIPELINES字典中定义
上記では、設定ファイルはのsettings.py、このパイプラインのクラスを追加します。
ITEM_PIPELINES = { 'Test.pipelines.TestPipeline': 300, # 300表示的是优先级,数值越小优先级越高,优先级高的先执行 'Test.pipelines.TestPipelineByMySQL': 400, # 自定义的管道类添加到此字典时才会被调用 'Test.pipelines.TestPipelineByRedis': 500, # 自定义的管道类添加到此字典时才会被调用 }
Redisの中で永続データをクエリ:
lrange blog_info 0 -1