基于Python-Scrapy-mimetype的过滤器可避免非文本文件下载

2024-10-01 07:43:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个正在运行的scrapy项目,但它是带宽密集型的,因为它试图下载大量的二进制文件(zip、tar、mp3等等)。在

我认为最好的解决方案是基于mimetype(Content-Type:)HTTP报头过滤请求。我看了看代码,发现了这个设置:

DOWNLOADER_HTTPCLIENTFACTORY = 'scrapy.core.downloader.webclient.ScrapyHTTPClientFactory'

我把它改成: DOWNLOADER_HTTPCLIENTFACTORY='myproject.WebClient.ScrapyHttpClient工厂'

在使用ScrapyHTTPPageGetter时,以下是突出显示的编辑:

^{pr2}$

我觉得这是错误的,我需要更多的破烂友好的方式取消/删除请求后,立即确定它是不需要的mimetype。而不是等待整个数据被下载。在

编辑:
我特别问这个问题self.factory.noPage(Exception('Incorrect Content-Type'))这是取消请求的正确方法吗。在

更新1:
我当前的设置已经使垃圾服务器崩溃,所以请不要尝试使用上面相同的代码来解决问题。在

更新2:
我建立了一个基于Apache的网站,使用以下结构进行测试:

/var/www/scrapper-test/Zend -> /var/www/scrapper-test/Zend.zip (symlink)
/var/www/scrapper-test/Zend.zip

我注意到,Scrapy丢弃了带有.zip扩展名的,但是删除了没有.zip的扩展名,尽管它只是指向它的符号链接。在


Tags: 项目代码test编辑varwwwtypedownloader
3条回答

解决方案是设置一个Node.js代理,并配置scray通过http_proxy环境变量使用它。在

proxy应该做的是:

  • 从Scrapy获取HTTP请求并将其发送到正在爬网的服务器。然后它将响应从返回给Scrapy,即截获所有HTTP流量。在
  • 对于二进制文件(基于您实现的启发式),它向Scrapy发送403 Forbidden错误并立即关闭请求/响应。这有助于节省时间,交通和刮擦不会崩溃。在

代理代码示例

真的很管用!在

http.createServer(function(clientReq, clientRes) {
    var options = {
        host: clientReq.headers['host'],
        port: 80,
        path: clientReq.url,
        method: clientReq.method,
        headers: clientReq.headers
    };


    var fullUrl = clientReq.headers['host'] + clientReq.url;

    var proxyReq = http.request(options, function(proxyRes) {
        var contentType = proxyRes.headers['content-type'] || '';
        if (!contentType.startsWith('text/')) {
            proxyRes.destroy();            
            var httpForbidden = 403;
            clientRes.writeHead(httpForbidden);
            clientRes.write('Binary download is disabled.');
            clientRes.end();
        }

        clientRes.writeHead(proxyRes.statusCode, proxyRes.headers);
        proxyRes.pipe(clientRes);
    });

    proxyReq.on('error', function(e) {
        console.log('problem with clientReq: ' + e.message);
    });

    proxyReq.end();

}).listen(8080);

我构建这个中间件是为了排除不在正则表达式白名单中的任何响应类型:

from scrapy.http.response.html import HtmlResponse
from scrapy.exceptions import IgnoreRequest
from scrapy import log
import re

class FilterResponses(object):
    """Limit the HTTP response types that Scrapy dowloads."""

    @staticmethod
    def is_valid_response(type_whitelist, content_type_header):
        for type_regex in type_whitelist:
            if re.search(type_regex, content_type_header):
                return True
        return False

    def process_response(self, request, response, spider):
        """
        Only allow HTTP response types that that match the given list of 
        filtering regexs
        """
        # each spider must define the variable response_type_whitelist as an
        # iterable of regular expressions. ex. (r'text', )
        type_whitelist = getattr(spider, "response_type_whitelist", None)
        content_type_header = response.headers.get('content-type', None)
        if not type_whitelist:
            return response
        elif not content_type_header:
            log.msg("no content type header: {}".format(response.url), level=log.DEBUG, spider=spider)
            raise IgnoreRequest()
        elif self.is_valid_response(type_whitelist, content_type_header):
            log.msg("valid response {}".format(response.url), level=log.DEBUG, spider=spider)
            return response
        else:
            msg = "Ignoring request {}, content-type was not in whitelist".format(response.url)
            log.msg(msg, level=log.DEBUG, spider=spider)
            raise IgnoreRequest()

要使用它,请将其添加到设置.py公司名称:

^{pr2}$

也许已经很晚了。您可以使用Accept头来过滤要查找的数据。在

相关问题 更多 >