Неполные наборы данных - журнал ничего не показывает

У меня есть актер с чирио-сканером, который просматривает список из примерно 5500 URL-адресов (urlList)

URL-адреса - это страницы результатов, на которых есть скрипт, содержащий файл json. В json добавлен текст, поэтому он не «чистый», поэтому я извлекаю его в константе и проверяю, есть ли совпадение в операторе «if». Если есть совпадение, я ползу.

Теперь. Моя проблема в том, что статистика поискового робота + журналы, кажется, указывают на то, что все URL-адреса просканированы. Проблема в том, что это не так. В журналах я вижу некоторые тайм-ауты (пример ниже), но эти URL-адреса просто возвращаются в список запросов. Такой URL-адрес, как "example.com", выглядит нормально в журналах, и при поиске на странице есть данные + json, но он не выводится в результатах.

Я не могу понять, что не так, но подозреваю, что это утверждение «если» делает что-то странное. Может быть, json найден, но еще не загружен, или что-то еще.

Могли бы некоторые из вас, умные, протянуть руку помощи?

Пример статистики Статистика последнего запроса сканера: {"avgDurationMillis": 2554, "perMinute": 580, "finished": 5445, "failed": 0, "retryHistogram": [5151,276,18] }

Пример тайм-аута: Ошибка: CheerioCrawler: время ожидания запроса истекло через 30 секунд. и т. д. и т. д.

const Apify = require('apify');

Apify.main(async () => {
  const requestList = new Apify.RequestList({ sources: urlList })
  await requestList.initialize();

  const crawler = new Apify.CheerioCrawler({
    requestList,
    useApifyProxy: true,
    handlePageFunction: async ({ $, request }) => {

      const jsonString = $('script:contains("__thisvalue__")').text();
      if (jsonString.match(/\[{[\d\D]*}\]/) !== null) {
        const json = JSON.parse(jsonString.match(/\[{[\d\D]*}\]/));
        let i = 0;
        for (i = 0; i < json.length; i++) {

          await Apify.pushData({
            //do some crawling
            url: request.url

          });
        }
      }
    },
    handleFailedRequestFunction: async ({ request }) => {
      console.log(`Copy of request: ${request}`);
    },
  });
  await crawler.run();
  return 'Done'

});

person Simon    schedule 06.12.2019    source источник
comment
1. Было бы неплохо включить журналы, ссылку на набор данных и т. Д. 2. Я не уверен, почему вы перебираете json.length перед тем, как нажимать? 3. Тайм-аут - это нормально, если он не наступает для всех URL-адресов. По умолчанию есть 3 попытки, которые должны решить эту проблему. 4. Статистика говорит о том, что все URL-адреса обработаны до конца, некоторые из них были повторены один или два раза до успеха.   -  person Lukáš Křivka    schedule 06.12.2019
comment
Не могу публично поделиться журналами / набором данных, но отправили их вам. Я зацикливаюсь, потому что в json есть несколько объектов, например. {id: 1, name: name1}, {id: 2, name: name}. Итак, я зацикливаюсь на извлечении каждого объекта. 3 и 4. Точно, и это моя главная проблема. Все выглядит нормально, но предметов не хватает.   -  person Simon    schedule 09.12.2019
comment
При отладке первое правило - всегда добавлять журналы. Так что добавьте журнал, если jsonString пуста, а также если она не совпадает. Также выгрузите HTML-код в хранилище ключей и значений, чтобы вы получили именно то, что получили обратно. Возможно, вместо этого у вас есть капча, но вы вообще не проверяете контент.   -  person Lukáš Křivka    schedule 09.12.2019
comment
Спасибо, Лукас. Смотрите мое решение ниже. Не знаю, есть ли лучший подход. Кстати. согласен с частью ведения журнала, у меня есть больше журналов при тестировании и т. д., но минимизируйте ведение журнала в процессе производства.   -  person Simon    schedule 09.12.2019


Ответы (1)


Нашел проблему. Эта строка:

if (jsonString.match(/\[{[\d\D]*}\]/) !== null)

Я создал if, чтобы убедиться, что я просканировал страницы, на которых была правильная строка json (например, данные, которые я хочу сканировать).

Но иногда скрипт еще не выводил данные (может быть, cheerio может быть слишком быстрым?), Поэтому страницы, на которых должен быть результат, не сканировались, и из-за отсутствия ошибки эти URL-адреса не возвращались в запрос список для другого прогона.

Я просто изменил следующую строку и удалил все if. Теперь URL-адрес повторно оценивается 3 раза, если в json нет данных, и все URL-адреса в конечном итоге сканируются. Единственное предостережение: теперь в моих журналах появляются ошибки с TypeError: не удается прочитать свойство 'xyz', равное нулю.

const jsonString = JSON.parse($('script:contains("__thisvalue__")').text().match(/{[\d\D]*}}/))
person Simon    schedule 09.12.2019
comment
Cheerio не может загружаться слишком быстро, так как он просто загружает весь HTML-файл, ни больше, ни меньше. Также неплохо разделить код на более мелкие переменные и проверить их. Затем вы можете выдать настраиваемую ошибку вместо свойства невозможно прочитать .... Например, одна переменная для сценария, другая для соответствия и т. Д. Тогда вы точно знаете, что произошло, и можете отлаживать, почему эта часть была другой. - person Lukáš Křivka; 10.12.2019
comment
Привет, Лукас. Попался. Иногда кажется, что тег скрипта просто пуст при первом запуске, поэтому я подумал, что cheerio может быть слишком быстрым. Можно ли вручную вернуть URL-адрес в список запросов? Например, «если jsonString == null ...», а затем вернуть request.url в список запросов? Проблема в том, что из 5,500 URL-адресов некоторые всегда будут иметь пустые скрипты, в то время как другие кажутся пустыми на мгновение примерно в 3-4% случаев. - person Simon; 11.12.2019
comment
Мы решаем эту проблему, просто выдавая ошибку throw new Error('No script found');. Запрос будет автоматически повторен позже. Если это происходит часто, вы также можете увеличить maxRequestRetries параметр CherioCrawler. (по умолчанию 3) - person Lukáš Křivka; 12.12.2019