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

问题描述 投票:0回答:2

我正在使用管道将 Scrapy 爬取的文档缓存到数据库中,以便在更改项目解析逻辑时可以重新解析它们,而无需再次访问服务器。

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

我喜欢 scrapy 对 CSS 和 XPath 选择器的支持,否则我就用 lxml 解析器单独访问数据库。

有一段时间,我根本没有缓存文档并以正常方式使用 Scrapy - 即时解析项目 - 但我发现更改项目逻辑需要大量时间和资源的重新爬网。相反,我现在将文档正文与项目解析一起缓存,并且我希望可以选择让 Scrapy 从数据库中迭代这些文档,而不是抓取目标 URL。

我该如何修改 Scrapy,让我可以选择向其传递一组文档,然后单独解析它们,就好像它刚刚从网络上拉取它们一样?

python web-scraping scrapy
2个回答
1
投票

我认为自定义下载器中间件是一个好方法。这个想法是让这个中间件直接从数据库返回源代码,并且不要让 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)

不要忘记激活中间件


0
投票

对于其他人,请尝试使用HttpCacheMiddleware,如https://stackoverflow.com/a/10897298

中所述
© www.soinside.com 2019 - 2024. All rights reserved.