【问题标题】:How to deny some links which are similar to some that should be parsed by Scrapy?如何拒绝一些与 Scrapy 应该解析的链接相似的链接?
【发布时间】:2019-07-05 12:18:37
【问题描述】:

我正在尝试使用一些我想要拒绝的链接和我想要解析的产品页面来抓取电子商务商店。数据示例:

Parse:
domain.de/nike-Flasche-750-ml
domain.de/Nike-Tasche-schwarz-5
domain.de/Erima-Flasche-weiss-gruen-gelb-5
domain.de/Erima-Hose-rot-blau-gelb-weiss
domain.de/converse-4-Laufschuhe

Deny:
domain.de/service
domain.de/zahlung-versand
domain.de/Mein-Konto
domain.de/geschenkideen-fuer-sie

我已经尝试手动将所有内容添加到一个拒绝规则,然后为所有产品添加一个通用规则domain\.de\/([a-zA-Z0-9-]{2,}-) 那只蜘蛛一直在遍历所有类别,但从未解析过一个项目。

那我在on表达式里面试了一下:

domain\.de\/(?!zahlung-versand|service|Mein-Konto|geschenkideen-fuer-sie)([a-zA-Z0-9-]{2,}-)

否定前瞻的页面确实没有被爬取。但是,仍然没有抓取和解析任何产品。

如果我删除拒绝规则,则会解析产品以及应该在拒绝列表中的 URL,然后解析器会中断(因为该页面不包含产品数据/产品列表结构)。

在正则表达式中,事情似乎在起作用:

https://regex101.com/r/OtW6lb/1

编辑:

让蜘蛛继续运行的一个明显解决方案是,在蜘蛛在某处遇到错误时简单地返回。 但我想避免首先抓取页面(如果可能,通过正则表达式)

编辑 2:

我的规则在 JSON 中是这样的

"rules": [
    {
        "deny": ["\\.de\\/.*__"],
        "follow": false
    },
    {
        "allow": ["\\.de\\/([a-zA-Z0-9-]{2,}-)"],
        "follow": true,
        "use_content": true
    },
    {
        "allow": ["\\.de\\/(cat1|cat2|cat3|cat4)(?:_s[0-9]{1,})?$"],
        "follow": true
    }
],

然后,它们被分配到蜘蛛__init__()函数中:

for rule in self.MY_SETTINGS["rules"]:
allow_r = ()
if "allow" in rule.keys():
    allow_r = [a for a in rule["allow"]]

deny_r = ()
if "deny" in rule.keys():
    deny_r = [d for d in rule["deny"]]

restrict_xpaths_r = ()
if "restrict_xpaths" in rule.keys():
    restrict_xpaths_r = [rx for rx in rule["restrict_xpaths"]]

Sportygenspider.rules.append(Rule(
    LinkExtractor(
        allow=allow_r,
        deny=deny_r,
        restrict_xpaths=restrict_xpaths_r,
    ),
    follow=rule["follow"],
    callback='parse_item' if ("use_content" in rule.keys()) else None
))

使用此规则顺序,永远不会调用 use_content。虽然蜘蛛会遍历所有类别页面。 如果我删除了__ 的拒绝规则,则每个页面都会调用use_content,并且我必须对关于我们页面和类似页面中一些未满足的条件执行return

【问题讨论】:

  • 链接在html正文中的定位有区别吗?如果是这样,您可以使用 XPaths 来识别 html 的部分以在其中搜索链接。如果您愿意,请告诉我,我可以为您写一个示例解决方案...
  • 我也通过restrict_xpaths=() 参数考虑了这一点。排除页面的页眉和页脚可能会起作用。但在这种情况下,我想拒绝的一些 URL 嵌套在主导航中,就在应该解析的其他 URL 旁边。
  • 嗯很难说。拒绝域列表是否已修复?还是因页面而异?
  • 对于这家商店,我有一个正在构建的固定列表 - 但也有一些来自过滤器导航的动态 URL(我刚刚发现)。他们可以被__识别:domain.de/geschenkideen-fuer-sie__schuhgroesse
  • 你重新编译你的正则表达式了吗?它必须是一个正则表达式对象。不是字符串

标签: python-3.x scrapy web-crawler


【解决方案1】:
  • 您已使用链接提取规则列表初始化您的蜘蛛
  • 如果有多个或您的规则匹配一个链接,则只有first matching rule will be used to parse that link。这可以解释为什么除非您删除拒绝规则,否则不会调用您的回调 use_content。可能拒绝规则与允许规则匹配相同的链接。因此,链接仅由拒绝规则而不是允许规则处理。请记住,对于 LinkExtractor 对象
    • If you leave allow parameter empty the link extractor will match all links
    • deny 参数可用于将不应匹配的链接列入黑名单
    • 在您的情况下,deny 规则匹配所有与正则表达式不匹配的链接。
    • allow 规则匹配所有匹配正则表达式的链接,然后在这些链接上调用 use_content。但它不会处理已经被 deny 规则匹配的链接

在我看来,您好像需要将 allowdeny 组合成一个规则。 例如,将您的规则更改为此可能会更好地与您现有的代码一起使用

"rules": [
{
    "deny": ["\\.de\\/.*__"],
    "allow": ["\\.de\\/([a-zA-Z0-9-]{2,}-)"],
    "use_content": true
    "follow": false
},
{
    "deny": ["\\.de\\/.*__"],
    "allow": ["\\.de\\/(cat1|cat2|cat3|cat4)(?:_s[0-9]{1,})?$"],
    "follow": true
}
],

【讨论】:

  • 是的,你是对的 - 现在我已经按照你的建议在规则中设置了 allow、deny 和 restrict_xpaths。另外:'rules.append(Rule ..' 在我的代码中也被错误地缩进了——在 for 之后,所以只分配了最后一条规则,现在产品被刮掉了。
猜你喜欢
  • 2015-02-22
  • 2019-09-18
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 2010-09-25
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
相关资源
最近更新 更多