пятница, 16 ноября 2018 г.

Обработка xml в таблице google на примере zakupki.gov.ru

Получать информацию с различных сайтов можно по разному: 
  1. сидеть долго и упорно, отслеживая поступающую на сайт информацию,
  2. использовать специально предназначенные для этого парсеры,
  3. написать свой собственный велосипед - парсер.
В первом случае тратиться очень много времени, которое можно было бы использовать для общения с друзьями, коллегами, семьёй. Самое ценное, что есть у нас, это время. 
Во втором случае можно потратить очень много денег, которые можно было бы направить на приятное времяпровождение с друзьями, коллегами, семьёй. Ведь самое ценное, что есть у нас, это время. А время проведённое в хорошей компании бесценно.
Ну а для того, чтобы затраченное время и деньги перестали нас так волновать, надо написать скрипт, который будет брать информацию с нужного нам сайта. Так почему же не взяться за Официальный Сайт Единой Информационной Системы в сфере закупок.
Для начала ознакомимся со статьёй в которой описано каким образом можно получить ссылку на RSS ленту нужную именно нам.

 Если правильно составим запрос, то можно считать что половина дела сделана.
Остаётся дело за малым - скрипт, который нужно создать в таблице google.

function parseZakupki() {
  var url = 'http://zakupki.gov.ru/tinyurl/4995bdbb-597a-495b-9856-aff3a0d50b0a';
  var options={
      'header':'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1',
   }
  var xml = UrlFetchApp.fetch(url,options).getContentText();
  var document = XmlService.parse(xml);
  var root = document.getRootElement().getChildren('channel');
  var entries=root[0].getChildren('item');
  var sheetData=[]
  for (var i = 0; i < entries.length; i++) {
    var title = entries[i].getChild('title').getText();
    var link = entries[i].getChild('link').getText();
    var pubdate=new Date(entries[i].getChild('pubDate').getText())
    var who = entries[i].getChild('author').getText()
    var description=entries[i].getChild('description').getText().replace(/\<\/b>/g,'').replace(/\
/g,'\n').replace(/\/g,'\n').replace(/"/g,'"').replace(/ /g,'"').replace(/«/g,'"').replace(/»/g,'"').replace(/–/g,'–').split('\n\n')[1].split('\n')[1] for (var j=0;j<description.length;j++){ if (description[j].indexOf('Наименование объекта закупки:')!=-1) { var what=description[j].split(': ')[1];break; } } if (link.indexOf('http')==-1){ link='http://zakupki.gov.ru'+link } sheetData.push([Utilities.formatDate(pubdate, Session.getScriptTimeZone(), "dd.MM.YY HH:mm"),link ,title,what,who]) } SpreadsheetApp.getActiveSheet().getRange(2, 1, sheetData.length, sheetData[0].length).setValues(sheetData) }
Что делает скрипт: 
  1. Получает RSS ленту по адресу, который указан в url, притворяясь браузером Safari.
  2. Парсит xml (да, да RSS на самом деле простой xml файл).
  3. Заполняет активную страницу данными из RSS ленты в порядке Дата размещения, Ссылка, Название, Описание, Кто разместил, начиная со второй строчки. Первую можно будет использовать для заголовков.
Если поставить триггер на выполнение данному скрипту, можно будет получать нужную информацию в автоматическом режиме, не мониторя, сам сайт zakupki.gov.ru. При этом будем экономить время и деньги, которых нам так часто не хватает.
Эх, к этому скрипту прикрутить бы ещё бота Telegram, который бы по триггеру отправлял только новые данные.
Вопросы и здравая критика принимаются.

PS:
25.11.2018 поправил скрипт, т.к. заметил что zakupki на запросы RSS,без указания клиента, начал выдавать 403 ошибку.

14 комментариев:

  1. Роман, добрый день. Начал читать ваш блог, чтобы разобраться с гугл таблицами. Не подскажите, как составить график обзвона партнеров?

    У меня есть таблица с датой обзвона партнеров и следующей датой обзвона.
    То есть например последний звонок был 26.03.2019, какой скрипт прописать можно чтобы он автоматом выставлял следующую дату через 180 дней?

    Заранее спасибо за помощь.

    PS пока что полный чайник в таблицах, но с Вашим блогом надеюсь обзаведусь новыми знаниями.

    ОтветитьУдалить
    Ответы
    1. Здравствуйте, Тимур.
      Почему бы Вам не воспользоваться формулой.
      Допустим столбец А дата, столбец B дата следующего звонка. В столбец В введите формулу =A1+180.

      Удалить
  2. Пишет что недопустимый символ в 16 строке.

    ОтветитьУдалить
    Ответы
    1. Это из-за особенностей восприятия blogspot тегов, которые должны заменяться в описании закупки. Эта часть кода должна заменять существующие теги html на соответствующие знаки.
      Blogspot воспринимает некоторые из них как свои теги и переделывает под себя.

      Удалить
    2. а как исправить ее не подскажите? можете выложить текстовый документ с кодом и нормальными тегами?

      Удалить
    3. https://script.google.com/d/1mzDvVA8aMJ9XGStLjpYZRgJw31rY0AiwcRFl94dJDlo7R5GfGQFBQwyf/edit?usp=sharing
      Запросите доступ - предоставлю.

      Удалить
    4. Запросил. А подскажите пожалуйста по практике, может сверялись... ЕИС достоверную информацию шлет? Т.к. зная ЕИС и их постоянные сбои, возникают подозрения в полноте предоставляемых данных)

      Удалить
    5. Александр, вчера Вам на почту отправлял ответ и копию скрипта. Посмотрите почту.

      Удалить
  3. Добрый вечер. Все бы хорошо, но поисковый запрос бы передавать как параметр. Например лекарственный препарат.
    Пробую созданный запрос ему подсунуть,
    например
    http://zakupki.gov.ru/epz/order/extendedsearch/results.html?searchString=Цефтриаксон&morphology=on&pageNumber=1&sortDirection=true&recordsPerPage=_10&showLotsInfoHidden=false&fz44=on&fz223=on&sortBy=PRICE&af=on&ca=on&pc=on&pa=on&publishDateFrom=+&currencyIdGeneral=-1&contractStageList_0=on&contractStageList_1=on&contractStageList_2=on&contractStageList_3=on&contractStageList=0%2C1%2C2%2C3&extAttSearchEnable=false

    Error on line 80: The entity name must immediately follow the '&' in the entity reference.



    ОтветитьУдалить
    Ответы
    1. Начните со строчки
      var url = 'http://zakupki.gov.ru/epz/order/extendedsearch/rss.html?searchString=Цефтриаксон&morphology=on'
      Вполне может быть что запрос не очень правильный.

      Удалить
  4. Роман здравствуйте 🤝 скажите пожалуйста можно ли проделать такое с goszakup.gov.kz ?

    ОтветитьУдалить
    Ответы
    1. Здравствуйте.
      Если у сайта есть такой функционал, то можно попробовать переписать под него. Если нет, то нужно думать и смотреть как это лучше сделать.

      Удалить
  5. А как можно проверить по сайту, возможно ли вытащить rss с информацией или нет?)

    ОтветитьУдалить
    Ответы
    1. почитать о сайте (OK,google), в техподдержку обратиться, самому по сайту полазить, посмотреть. Других вариантов быть не должно).

      Удалить