我正在使用管道将 Scrapy 爬取的文档缓存到数据库中,以便在更改项目解析逻辑时可以重新解析它们,而无需再次访问服务器。
从缓存中进行 Scrapy 进程而不是尝试执行正常爬行的最佳方法是什么?
我喜欢 scrapy 对 CSS 和 XPath 选择器的支持,否则我就用 lxml 解析器单独访问数据库。
有一段时间,我根本没有缓存文档并以正常方式使用 Scrapy - 即时解析项目 - 但我发现更改项目逻辑需要大量时间和资源的重新爬网。相反,我现在将文档正文与项目解析一起缓存,并且我希望可以选择让 Scrapy 从数据库中迭代这些文档,而不是抓取目标 URL。
我该如何修改 Scrapy,让我可以选择向其传递一组文档,然后单独解析它们,就好像它刚刚从网络上拉取它们一样?
我认为自定义下载器中间件是一个好方法。这个想法是让这个中间件直接从数据库返回源代码,并且不要让 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)
不要忘记激活中间件。
对于其他人,请尝试使用HttpCacheMiddleware,如https://stackoverflow.com/a/10897298
中所述