将Scrapy指向本地缓存而不是执行正常的抓取过程

时间:2015-09-04 23:22:57

标签: python web-scraping scrapy

我使用管道将Scrapy中的文档缓存到数据库中,这样我就可以重新解析它们,如果我更改项目解析逻辑而不必再次点击服务器。

从缓存中获取Scrapy进程而不是尝试执行正常爬网的最佳方法是什么?

我喜欢scrapy对CSS和XPath选择器的支持,否则我只是用lxml解析器单独命中数据库。

有一段时间,我根本没有缓存文档并以正常方式使用Scrapy - 动态解析项目 - 但我发现更改项目逻辑需要时间和资源密集重新抓取。相反,我现在正在缓存文档正文以及项目解析,我想让Scrapy从数据库迭代这些文档而不是抓取目标URL。

我如何修改Scrapy,让我可以选择将一组文档传递给它,然后单独解析它们,就好像它刚刚将它从Web上拉下来一样?

1 个答案:

答案 0 :(得分:1)

我认为custom Downloader Middleware是一个很好的方法。我们的想法是让这个中间件直接从数据库返回源代码,不要让Scrapy发出任何HTTP请求。

示例实现(未经过测试,肯定需要错误处理):

import re

import MySQLdb
from scrapy.http import Response    
from scrapy.exceptions import IgnoreRequest
from scrapy import log
from scrapy.conf import settings


class CustomDownloaderMiddleware(object):
   def __init__(self, *args, **kwargs):
        super(CustomDownloaderMiddleware, self).__init__(*args, **kwargs)

        self.connection = MySQLdb.connect(**settings.DATABASE)
        self.cursor = self.connection.cursor()

   def process_request(self, request, spider):
       # extracting product id from a url
       product_id = re.search(request.url, r"(\d+)$").group(1)

       # getting cached source code from the database by product id
       self.cursor.execute("""
           SELECT
               source_code
           FROM
               products
           WHERE
               product_id = %s
       """, product_id)

       source_code = self.cursor.fetchone()[0]

       # making HTTP response instance without actually hitting the web-site
       return Response(url=request.url, body=source_code)

不要忘记activate the middleware