Как запретить некоторые ссылки, похожие на те, которые должны быть проанализированы Scrapy? - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь сканировать интернет-магазин с некоторыми ссылками, которые я хочу запретить, и страницами продуктов, которые я хочу проанализировать.Пример данных:

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,}-) Этот паук продолжал проходить по всем категориям, ноникогда не анализировал ни одного элемента.

Тогда я попробовал это в выражении:

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

Страницы негативного взгляда действительно не падают.Но, тем не менее, никакие продукты не сканируются и не анализируются.

Если я удаляю запрещающие правила, анализируются товары, а также URL-адреса, которые должны быть в списке запрещенных, а затем анализатор прерывается (так как страница не 't содержит данные о продукте / структуру списка продуктов).

В регулярных выражениях, похоже, все работает:

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

Редактировать:

Один очевидныйРешение, чтобы заставить паука продолжать работать, было бы просто сделать возврат в случае, если у паука где-то возникнет ошибка.Но я бы хотел избежать сканирования страниц в первую очередь (с помощью регулярных выражений, если это возможно)

Edit 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 по некоторым невыполненным критериям со страницы о нас и тому подобное.

1 Ответ

0 голосов
/ 12 февраля 2019
  • Вы инициализировали своего паука со списком правил для извлечения ссылки
  • Если несколько ссылок соответствуют одному или вашим правилам, то для анализа будет использоваться только первое соответствующее правило .эта ссылка .Это может объяснить, почему ваш обратный вызов use_content не вызывается, если вы не удалите правило запрета.Вероятно, правило запрета соответствует тем же ссылкам, что и правило разрешения.Поэтому ссылки обрабатываются только правилом deny, а не правилом allow.Помните, что для объектов LinkExtractor
    • Если вы оставите параметр allow пустым, то экстрактор ссылок будет соответствовать всем ссылкам
    • deny параметр может использоваться для черного списка ссылок, которые не должны совпадать
    • В вашем случае правило deny соответствует всем ссылкам, которые не соответствуют регулярному выражению.
    • Правило allow соответствует всем ссылкам, которые соответствуют регулярному выражению, и затем вызывает use_content для них.Но он не будет обрабатывать ссылки, которые уже соответствуют правилу deny

Мне кажется, что вам нужно объединить разрешить и запретить в одном правиле.Например, изменение ваших правил на это может лучше работать с существующим кодом

"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
}
],
...