2 августа 2016 в 11:16

Небольшой скрипт для отслеживания цен avito из Google Spreadsheet tutorial

Хочу поделиться с сообществом небольшим скриптом для загрузки цен с сайта объявлений AVITO в Google Spreadsheet. Вдруг кому-нибудь еще пригодится.

Логика такая — в цикле бежим по ячейкам таблицы с адресами и запрашиваем странички. Из полученных страниц получаем цену и подставляем в соседние ячейки. Запуск скрипта через пункт меню Avito -> Update Prices.

Page Sample
(наименнннование sic!)

Далее пошаговая инструкция. Заранее прошу прощения, у не владеющих, что названия и пункты меню на английском языке. Думаю по картинкам вы сможете воспроизвести шаги в русском интерфейсе.

Чтобы получить подобную страничку делаем следующее:

1) Создаем документ Google Spreadsheet
(https://docs.google.com/spreadsheets -> Start a new spreadsheet -> Blank)
Create New Blank Spreadsheet

2) Поиском находим на авито интересующие нас объявления и подставляем их адреса в наш документ. Должно получиться что-то вроде
Fill URLs

3) Создаем Named Range: «URL». Для этого выбираем Data -> Named Ranges…
Named Ranges
Ставим курсор на первый адрес в нашем списке и нажимаем + Add a range, вводим «URL» и нажимаем Done.
Named Range Params

4) Заходим в редактор скриптов Tools -> Script Editor
Run Script Editor

Стираем существующий и вставляем следующий код:
function priceToInt(pPrice){
  var res = parseInt(pPrice.replace(/\D/g, ""));
  return res;
}
  
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Avito')
      .addItem('Update Prices', 'updatePrices')
      .addToUi();
}

function updatePrices() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var range = ss.getRangeByName('URL');  
  var firstRow = range.getRow();
  var firstCol = range.getColumn();
  var howManyRowsRead = 50;
  Logger.log('firstRow = ' + firstRow);
  Logger.log('firstCol = ' + firstCol);
  
  var data = sheet.getRange(firstRow, firstCol, howManyRowsRead, 1).getValues();

  LLL: for (var i = 0; i < data.length; i++) {
    var url = data[i][0];
    
    if (!url) break LLL;
    
    var prevPriceCell = sheet.getRange(firstRow+i, firstCol+2);
    var priceCell = sheet.getRange(firstRow+i, firstCol+1);
    prevPriceCell.setValue(priceCell.getValue());
    priceCell.setValue('0');
    
    var options =
        {
          headers : {'Cache-Control' : 'max-age=0', 
                     'Referer': 'https://www.avito.ru/tolyatti/doma_dachi_kottedzhi/prodam?pmax=2700000&pmin=600000&geo=53.50804496509228%2C49.1193614935664%2C53.52551454627456%2C49.183133695104516%2C15%2Cf',
                     'Upgrade-Insecure-Requests': '1',
                     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'},           
          muteHttpExceptions: true,
        };
    var response = UrlFetchApp.fetch(url, options).getContentText();
    var p1 = '<span itemprop="price">';
    var l1 = response.indexOf(p1);
    var p2 = '</span>';
    var l2 = response.indexOf(p2, l1 + p1.length);
    Logger.log('l1 = ' + l1);
    Logger.log('l2 = ' + l2);
    if (l1 != -1 && l2 != -1)
    {
      var price = response.substring(l1 + p1.length,l2);      
      Logger.log('price = ' + price);
      priceInt = priceToInt(price);
      Logger.log('priceInt = ' + priceInt);
      priceCell.setValue(priceInt);
    }
  }
}


Сохраняем. Имя скрипта значения не имеет.
Save Script

На этом все готово! Можно закрыть редактор скриптов, обновить Spreadsheet. Должен появиться пункт меню Avito -> Update Prices.
Выбираем его, даем нужные права и смотрим как заполняются цены в нашем документе.
PS Если в процессе произошла ошибка — в поиске причины помогут логи доступные из редактора скриптов Tools -> Script Editor -> View -> Logs.
@LexB
карма
20,0
рейтинг 0,0
Похожие публикации
Самое читаемое Разработка

Комментарии (32)

  • +11
    Уметь писать скрипты в Spreadsheets, это полезно)
    Но конкретно вашу задачу можно решить в два клика с помощью функции ImportXML
    Она имеет свои ограничения, но здесь подходит
    1. Правой кнопкой по цене, открываем веб инспектор на нужном элементе => Copy XPATH
    2. В Spreadsheets пишем =IMPORTXML(URL, XPATH)
    3. Profit

    Вот небольшой пример
    • 0
      т.е. если будет список из 500 объявлений, каждый раз, каждый зашедший человек будет загружать 500 страниц с авито?? :)
      • 0
        Результат запроса кэшируется, так что все ссылки будут загружены по одному разу)
        • 0
          А разве смысл скрипта в статье не в том чтобы отслеживать цены?
          Если страницы закэшируются, то какой смысл в них если цены позже изменятся?
          • 0
            Можно добавить параметр в URL, или просто ничего не делать, т.к. кэш живет не очень долго, около часа.
            Если вам нужно чаще обновлять цены или другая сложная логика, то конечно такое простое решение здесь не подойдет.
    • 0
      а так http://elibrary.ru/ парсить нельзя?
      у меня не получилось, что-то.
      • 0
        Основная проблема на elibrary — переход по страницам динамический. Первая страница со списком авторов или публикаций содержит параметры. Переход на следующие выполняется динамически через js. Но это можно обойти добавляя в адрес &pagenum=X с номером нужной страницы. Могу помочь с написанием паука.
  • 0

    del

  • +2
    Я так понимаю, данный вариант «парсинга! авито не приведёт к блокировке по IP — ну не будет же авито блокировать гугл!
    Также могу предложить парсить мобильную версию сайта — там можно вытаскивать телефоны (этакая „метаинформация“ — можно определить различных „барыг“ и риэлтеров, маскирующихся по частных лиц.)
    • 0
      ну не будет же авито блокировать гугл!
      А почему бы и нет! Авито нужна посещаемость и чтоб рекламу смотрели, а не подгружали всё через Гугл. Кстати, Гугл Докс уже использовали для DDoS, пока сам Гугл не прикрыл это дело.
  • 0
    Через какое время забанит?
  • –1
    var sheet = SpreadsheetApp.getActiveSheet();
    var ss = SpreadsheetApp.getActiveSpreadsheet();

    Не очень понятно, что Вы здесь делаете.
    В "sheet" у вас хранится активная таблица. В "ss" — активный лист. А затем в активной таблице Вы ищете диапазон с именем "URL". Зачем его искать по всей таблице, если он у вас будет находиться только в активном листе.


    То есть, если Вы хотели получить активную таблицу и в ней активный лист, то, на мой взгляд, это должно выглядеть следующим образом:


    var sheet = SpreadsheetApp.getActiveSpreadsheet();
    var ss = sheet.getActiveSheet();

    И затем все манипуляции проводить уже с активным листом "ss".

    • +1
      В «sheet» у вас хранится активная таблица. В «ss» — активный лист.

      Наоборот.

      Документация — https://developers.google.com/apps-script/reference/spreadsheet/.
      Все просто, getRangeByName есть только у Spreadsheet-а. У Sheet-а есть getNamedRanges() NamedRange[]. Можно перебрать циклом, но особого смысла нет.
      • 0

        Хорошо, убедили)
        Очень полезный метод getRangeByName, сам до него не добрался, поэтому благодарю за статью)

  • 0
    Примерно так бы выглядел хабр лет 15 тому назад.
  • 0
    Спасибо за статью. А язык так и остается Basic + гугловский spreadsheet?
    • 0
      Скрипты в spreadsheets пишутся на JavaScript
  • 0
    Немного не в тему вопрос, но возможно кто-то знает на него ответ…
    Дело в том, что есть на авито — частники, а есть — магазины,
    Так вот, по клику на магазин, можно сразу увидеть все объявления этого магазина
    Вопрос в следующем: Как узнать все объявления, закреплённые за частником?
    Спасибо.
    • 0
      Подозреваю, что можно как-то сделать по номеру телефона, если судить по комментарию
      • 0
        Да, только вот телефоны на сайте представлены не в числовом виде, а в виде картинки…
        Довольно интересно узнать, как это всё провернуть.
        • 0
          Если вам нужно только одинаковые найти, есть ли разница картинка это или текст?
          • 0
            Хмм, истину глаголишь.
            Только вот где тот человек, который всё это интерпретирует по уму-разуму.
            • 0
              Т.е. сделает за вас?
              На фрилансе полно таких людей, с готовыми парсерами. (платно, конечно)
  • 0
    Спасибо, пригодилось )
  • 0
    glisa.ru telegram и wget в crone решают большинство моих задач с avito.
  • 0
    Пользовался ли кто онлайн сервисами по мониторингу цен и товаров на Avito, которые отслеживают по заданным критериям поиска и автоматически уведомляют по e-mail? Одно время искал, приглянулся smartavito.ru. Но может что поинтереснее есть?
    • +1
      Использовал avigram.ru, попробуйте, может подойдет.
    • +1
      glisa.ru, уведомления на e-mail + telegram.
    • +1
      На Авито можно сохранить поиск с заданными параметрами. Новые объявления будут приходить на почту.
      • +1
        Ток он присылает через день и шлак, который не ушел в первый день.
    • 0
      Спасибо :)
  • 0
    Это реклама продвижение Google Spreadsheet? :)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.