Хочу поделиться с сообществом небольшим скриптом для загрузки цен с сайта объявлений 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.
Поделиться с друзьями
-->

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


  1. Scalar
    02.08.2016 11:44
    +11

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

    Вот небольшой пример


    1. aavezel
      02.08.2016 12:15

      т.е. если будет список из 500 объявлений, каждый раз, каждый зашедший человек будет загружать 500 страниц с авито?? :)


      1. Scalar
        02.08.2016 12:26

        Результат запроса кэшируется, так что все ссылки будут загружены по одному разу)


        1. zulkas
          02.08.2016 13:19

          А разве смысл скрипта в статье не в том чтобы отслеживать цены?
          Если страницы закэшируются, то какой смысл в них если цены позже изменятся?


          1. Scalar
            02.08.2016 13:57

            Можно добавить параметр в URL, или просто ничего не делать, т.к. кэш живет не очень долго, около часа.
            Если вам нужно чаще обновлять цены или другая сложная логика, то конечно такое простое решение здесь не подойдет.


    1. ksider
      02.08.2016 13:54

      а так http://elibrary.ru/ парсить нельзя?
      у меня не получилось, что-то.


  1. zvirusz
    02.08.2016 11:44

    del


  1. mihmig
    02.08.2016 11:50
    +2

    Я так понимаю, данный вариант «парсинга! авито не приведёт к блокировке по IP — ну не будет же авито блокировать гугл!
    Также могу предложить парсить мобильную версию сайта — там можно вытаскивать телефоны (этакая „метаинформация“ — можно определить различных „барыг“ и риэлтеров, маскирующихся по частных лиц.)


    1. ModoStudio
      03.08.2016 10:32

      ну не будет же авито блокировать гугл!
      А почему бы и нет! Авито нужна посещаемость и чтоб рекламу смотрели, а не подгружали всё через Гугл. Кстати, Гугл Докс уже использовали для DDoS, пока сам Гугл не прикрыл это дело.


  1. mapatka
    02.08.2016 11:55

    Через какое время забанит?


  1. garikbesson
    02.08.2016 12:33
    -1

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

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


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


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

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


    1. LexB
      02.08.2016 12:52
      +1

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

      Наоборот.

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


      1. garikbesson
        03.08.2016 09:12

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


  1. yul
    02.08.2016 13:16

    Примерно так бы выглядел хабр лет 15 тому назад.


  1. rooless
    02.08.2016 13:24

    Спасибо за статью. А язык так и остается Basic + гугловский spreadsheet?


    1. Scalar
      02.08.2016 13:58

      Скрипты в spreadsheets пишутся на JavaScript


  1. Anti-Dot
    02.08.2016 13:24

    Немного не в тему вопрос, но возможно кто-то знает на него ответ…
    Дело в том, что есть на авито — частники, а есть — магазины,
    Так вот, по клику на магазин, можно сразу увидеть все объявления этого магазина
    Вопрос в следующем: Как узнать все объявления, закреплённые за частником?
    Спасибо.


    1. AVX
      02.08.2016 14:41

      Подозреваю, что можно как-то сделать по номеру телефона, если судить по комментарию


      1. Anti-Dot
        02.08.2016 14:48

        Да, только вот телефоны на сайте представлены не в числовом виде, а в виде картинки…
        Довольно интересно узнать, как это всё провернуть.


        1. Denai
          02.08.2016 15:28

          Если вам нужно только одинаковые найти, есть ли разница картинка это или текст?


          1. Anti-Dot
            02.08.2016 15:55

            Хмм, истину глаголишь.
            Только вот где тот человек, который всё это интерпретирует по уму-разуму.


            1. r00tGER
              04.08.2016 12:03

              Т.е. сделает за вас?
              На фрилансе полно таких людей, с готовыми парсерами. (платно, конечно)


  1. nickneo
    02.08.2016 17:07

    Спасибо, пригодилось )


  1. tea
    02.08.2016 23:29

    glisa.ru telegram и wget в crone решают большинство моих задач с avito.


  1. XogN
    03.08.2016 11:52

    Пользовался ли кто онлайн сервисами по мониторингу цен и товаров на Avito, которые отслеживают по заданным критериям поиска и автоматически уведомляют по e-mail? Одно время искал, приглянулся smartavito.ru. Но может что поинтереснее есть?


    1. akov
      03.08.2016 18:37
      +1

      Использовал avigram.ru, попробуйте, может подойдет.


    1. tea
      04.08.2016 09:31
      +1

      glisa.ru, уведомления на e-mail + telegram.


    1. vilgood
      04.08.2016 11:57
      +1

      На Авито можно сохранить поиск с заданными параметрами. Новые объявления будут приходить на почту.


      1. akov
        04.08.2016 15:20
        +1

        Ток он присылает через день и шлак, который не ушел в первый день.


    1. XogN
      04.08.2016 13:04

      Спасибо :)


  1. webdi
    09.08.2016 13:05

    Это реклама продвижение Google Spreadsheet? :)