scrapy 实战(三)页面抓取完成如何同步到服务端

2017-01-22

上次讲到了,如何提取页面中的图片资源。

接下来,介绍页面抓取完成如何同步到服务端 或者写入数据库。

首先, 在 settings.py 添加一行设置

# 设置 抓取的页面 post 到服务器的 地址  
SERVER_URL = 'http://localhost:8000/api/entities/'  

接着,在写 scrapy 的 提交信息的 pipelines.py 之前我们先要写一个重复检查的 pipeline避免重复提交信息到数据库,导致脏数据的产生。

# -*- coding: utf-8 -*-  
  
# Define your item pipelines here  
#  
# Don't forget to add your pipeline to the ITEM_PIPELINES setting  
# See: [http://doc.scrapy.org/en/latest/topics/item-pipeli...](http://doc.scrapy.org/en/latest/topics/item-pipeline.html)  
  
from hashlib import md5  
import requests  
  
from scrapy.exceptions import DropItem  
from andromeda import settings  
  
  
class DuplicatesPipeline(object):  
  
    def process_item(self, item, spider):
        # 这里主要是拿商品原始链接计算 md5   
        identified_code     = md5(item['origin_link']).hexdigest()  

        #生成 检查商品的 URL  
        check_url           = "{url}/{identified_code}".format(  
            url = settings.SERVER_URL,  
            identified_code = identified_code,  
        )  
        res = requests.head(check_url)  
        
        # 提交信息后判断信息是否存在
        if res.status_code  == 200:
            #如果存在 DROP  
            raise DropItem("Duplicate entity found: %s", item)  
        else:  
            return item  
  

以上代码主要叙述了:

  1. 计算爬去商品唯一 值, 我这里用了 md5 当然,你也可以用其他方式。

  2. 去服务器检查信息是否存在。这里用了 HEAD 方法去请求服务器,用 GET 的话感觉比较消耗网络资源 (注,服务器需要允许 HEAD 方法不然永远返回 405)

  3. 判断服务器返回的响应码,200 的话就直接 DROP

继续,检查完信息是否重复后,我们就可以提交信息到服务端。

class PostEntityPipeline(object):  
  
    def process_item(self, item, spider):  
        res = requests.post(settings.SERVER_URL, json=dict(item))  
        if res.status_code == 200:  
            return item  
        else:  
            logging.error(res.text)  

以上代码很简单, 将 item 转换为字典。然后,通过 requests 提交到服务端。

最后,我们需要在 settings.py 中加入下面的配置

    
    # Configure item pipelines  
    # See [http://scrapy.readthedocs.org/en/latest/topics/ite...](http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html)  
    ITEM_PIPELINES = {  
        'andromeda.pipelines.DuplicatesPipeline': 100,    # 检查重复  
        'scrapy.pipelines.images.ImagesPipeline': 300,    # 下载图片
        'andromeda.pipelines.PostEntityPipeline': 500,    # 提交信息到服务端  
    }
    # 后面的数字代表程序执行的优先级

项目源代码