Scrapy CrawlSpider 基于 start_urls 的动态规则?

2023-12-11

我正在编写一个 Scrapy 抓取工具,它使用 CrawlSpider 来抓取网站,检查其内部链接,并抓取任何外部链接(域与原始域不同的链接)的内容。

我设法用两条规则来做到这一点,但它们是基于正在爬网的网站的域。如果我想在多个网站上运行它,我会遇到问题,因为我不知道我当前所在的“start_url”,所以我无法适当地更改规则。

这是我到目前为止想到的,它适用于一个网站,但我不确定如何将其应用于一系列网站:

class HomepagesSpider(CrawlSpider):
    name = 'homepages'

    homepage = 'http://www.somesite.com'

    start_urls = [homepage]

    # strip http and www
    domain = homepage.replace('http://', '').replace('https://', '').replace('www.', '')
    domain = domain[:-1] if domain[-1] == '/' else domain

    rules = (
        Rule(LinkExtractor(allow_domains=(domain), deny_domains=()), callback='parse_internal', follow=True),
        Rule(LinkExtractor(allow_domains=(), deny_domains=(domain)), callback='parse_external', follow=False),
    )

    def parse_internal(self, response):

        # log internal page...

    def parse_external(self, response):

        # parse external page...

这可能可以通过在调用抓取器时将 start_url 作为参数传递来完成,但我正在寻找一种在抓取器本身内以编程方式执行此操作的方法。

有任何想法吗? 谢谢!

Simon.


我找到了一个非常相似的问题并使用接受的答案中提供的第二个选项来开发此问题的解决方法,因为它在 scrapy 中不支持开箱即用。

我创建了一个函数,它获取 url 作为输入并为其创建规则:

def rules_for_url(self, url):

    domain = Tools.get_domain(url)

    rules = (
        Rule(LinkExtractor(allow_domains=(domain), deny_domains=()), callback='parse_internal', follow=True),
        Rule(LinkExtractor(allow_domains=(), deny_domains=(domain)), callback='parse_external', follow=False),
    )

    return rules

然后我重写了 CrawlSpider 的一些函数。

  1. 我将 _rules 更改为字典,其中键是不同的网站域,值是该域的规则(使用rules_for_url)。 _rules 的填充完成于_compile_rules

  2. 然后我做出适当的改变_requests_to_follow and _response_downloaded支持新的使用方式_rules.

_rules = {}

def _requests_to_follow(self, response):
    if not isinstance(response, HtmlResponse):
        return
    seen = set()

    domain = Tools.get_domain(response.url)
    for n, rule in enumerate(self._rules[domain]):
        links = [lnk for lnk in rule.link_extractor.extract_links(response) 
                 if lnk not in seen]
        if links and rule.process_links:
            links = rule.process_links(links)
        for link in links:
            seen.add(link)
            r = self._build_request(domain + ';' + str(n), link)
            yield rule.process_request(r)

def _response_downloaded(self, response):

    meta_rule = response.meta['rule'].split(';')
    domain = meta_rule[0]
    rule_n = int(meta_rule[1])

    rule = self._rules[domain][rule_n]
    return self._parse_response(response, rule.callback, rule.cb_kwargs, rule.follow)

def _compile_rules(self):
    def get_method(method):
        if callable(method):
            return method
        elif isinstance(method, six.string_types):
            return getattr(self, method, None)

    for url in self.start_urls:
        url_rules = self.rules_for_url(url)
        domain = Tools.get_domain(url)
        self._rules[domain] = [copy.copy(r) for r in url_rules]
        for rule in self._rules[domain]:
            rule.callback = get_method(rule.callback)
            rule.process_links = get_method(rule.process_links)
            rule.process_request = get_method(rule.process_request)

查看原来的功能here.

现在,蜘蛛将简单地遍历 start_urls 中的每个 url,并创建一组特定于该 url 的规则。然后对每个正在抓取的网站使用适当的规则。

希望这对将来遇到这个问题的人有所帮助。

Simon.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scrapy CrawlSpider 基于 start_urls 的动态规则? 的相关文章

随机推荐

  • 在php中显示链接

    我正在尝试将存储在 mysql 中的 URL 显示为 php 表中的链接 如下所示 echo td a href Resume a td 其中 row resume 使用 mysql fetch array 检索正确的数据 但是 文件链接之
  • 检测地理位置是否在复杂多边形中

    我们目前正在使用以下算法来检测地理点是否位于复杂多边形内 除非多边形穿过 180 经度线 否则效果很好 例如 在多边形中未检测到点 170 60 160 65 0 160 15 0 160 15 0 160 65 0 160 65 0 看下
  • ASP.NET,相当于PHP的Print_r函数吗?

    PHP Print r 对于打印数组和字典集合很有用 asp net 是在这个函数中构建的吗 你可以通过JavaScriptSerializer来实现 var json new JavaScriptSerializer Serialize
  • 安装 libv8 时出错:错误:无法构建 gem 本机扩展

    我做了一个 Rails 项目 rails new test bootstrap 成功了 移动到项目目录并添加宝石 gem therubyracer gem less rails Sprockets what Rails 3 1 uses f
  • Javascript/Typescript 将默认常量导出为异步函数调用的值

    我读了很多书 但还没有找到有效的解决方案 我见过的最接近的是这里 导出React中async函数的结果 请记住 我想导出一个对象 并且该对象是异步函数的结果 而不是导出异步函数定义本身 这是到目前为止我的用例和实现 我们有一个名为 conf
  • 有没有更简洁的正则表达式来完成这个任务?

    首先 对这个蹩脚的标题感到抱歉 但我想不出更好的标题 我需要测试密码以确保以下内容 密码必须至少包含以下 3 项 大写字母 小写字母 numbers 特殊字符 这是我想到的 它有效 但我想知道是否有更好的方法来做到这一点 Dim lower
  • 从 3D Rcpp NumericVector 索引切片

    您好 我有一个关于将 NumericVector 对象视为多维数组的非常简单的 Rcpp 问题 我找不到可能显而易见的答案 如果是这种情况 请先道歉 我对 C 的经验不足是罪魁祸首 如果我使用此处发布的答案 在 Rcpp 中构造 3D 数组
  • Android 支持 JDK 6 或 7 [重复]

    这个问题在这里已经有答案了 我是 Android 开发新手 我可以在 Android 中使用使用 JDK 7 开发的现有 Java 代码吗 这些函数使用 xerces dom xslt 和 xpathapi 目前 当我安装Android E
  • 错误:控制到达非 void 函数的末尾 [-Werror=return-type] } ^

    问题基本上是从给定的 n 个数字生成一个算术表达式 并且该表达式应该能被 101 整除 我们只能有 运算符 并且表达式是左关联的 我已经尝试了所有可用的解决方案 这些解决方案已经在堆栈溢出中提到过 例如用 else 关闭表达式等等 bool
  • Vbscript msxml12.XMLHTTP错误处理

    我使用这个 vbscript 代码来下载网页 Dim oXML Set oXML CreateObject msxm12 XMLHTTP oXML Open GET mysite com False oXML Send 如果没有这样的网站
  • PHP REGEX - 通过 preg_split 在换行符处将文本转换为数组

    EDITED 需要有关拆分数组的帮助 数组示例 array 0 gt some normal text some long text here and so on sometimes i m breaking down and some n
  • TFSPreview.com 和 Azure 持续部署 TFS 中的多个解决方案

    我最近尝试了 Microsoft 的 TFS in the cloud 服务 TFSPreview com 感觉 TFS 团队终于 明白了 TFSPreview com 可能会让我们从 GIT bug 跟踪器 powershell 切换过来
  • 如何在多列上创建索引

    我们有以下实体关系 其中用户属于特定组织 我的查询看起来像 select from User where org org 或 select from User where org org and type type 我在 User 类上有单
  • 是否可以将 Nesta CMS 包含到 Rails3 应用程序中?

    我想将 Nesta CMS 应用程序 安装 到 Rails3 应用程序上 这可能是 Nesta Sinatra 应用程序的原因 它应该是机架可安装层 但是您会怎么做 你将从哪里开始 有人有关于这个话题的经验吗 建议的文档 嘿卢卡 我一两个月
  • R中如何使用函数名的字符串来调用函数?

    我正在尝试使用给定的函数名称字符串来调用函数 E g print funcList 1 2 sin works mult lt mult 5 6 1 30 不起作用 func1 lt funcList 1 func1 5 6 func2 l
  • 从 URL 获取 HTTP 响应代码的最佳方法是什么?

    我正在寻找一种从 URL 获取 HTTP 响应代码 即 200 404 等 的快速方法 我不确定要使用哪个库 更新使用精彩请求库 请注意 我们使用的是 HEAD 请求 它应该比完整的 GET 或 POST 请求发生得更快 import re
  • 将片段实例保留在 FragmentPagerAdapter 中

    是否可以保留为某个片段创建的每个片段的实例 FragmentPagerAdapter在 的里面FragmentPagerAdapter 像这样的东西 Override public Object instantiateItem ViewGr
  • 同时下载多个页面?

    我想用Python编写一个脚本 它可以从数据库中获取url 并同时下载网页以加快速度 而不是等待每个页面一个接一个地下载 根据这个线程 Python 不允许这样做 因为称为全局解释器锁这可以防止多次启动相同的脚本 在投入时间学习 Twist
  • 无法从jupyterhub/jupyter笔记本调用tensorflow gpu,为什么?

    好吧 我认为八个小时足够我自己解决这个问题 所以我只想问大家 我在 jupyterhub 和 Jupyter Notebook 之外的名为 tensorflow 的虚拟环境中运行 tensorflow gpu 1 1 0 运行得很好 也就是
  • Scrapy CrawlSpider 基于 start_urls 的动态规则?

    我正在编写一个 Scrapy 抓取工具 它使用 CrawlSpider 来抓取网站 检查其内部链接 并抓取任何外部链接 域与原始域不同的链接 的内容 我设法用两条规则来做到这一点 但它们是基于正在爬网的网站的域 如果我想在多个网站上运行它