Логика такая — в цикле бежим по ячейкам таблицы с адресами и запрашиваем странички. Из полученных страниц получаем цену и подставляем в соседние ячейки. Запуск скрипта через пункт меню Avito -> Update Prices.
(наименнннование sic!)
Далее пошаговая инструкция. Заранее прошу прощения, у не владеющих, что названия и пункты меню на английском языке. Думаю по картинкам вы сможете воспроизвести шаги в русском интерфейсе.
Чтобы получить подобную страничку делаем следующее:
1) Создаем документ Google Spreadsheet
(https://docs.google.com/spreadsheets -> Start a new spreadsheet -> Blank)
2) Поиском находим на авито интересующие нас объявления и подставляем их адреса в наш документ. Должно получиться что-то вроде
3) Создаем Named Range: «URL». Для этого выбираем Data -> Named Ranges…
Ставим курсор на первый адрес в нашем списке и нажимаем + Add a range, вводим «URL» и нажимаем Done.
4) Заходим в редактор скриптов Tools -> 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);
}
}
}
Сохраняем. Имя скрипта значения не имеет.
На этом все готово! Можно закрыть редактор скриптов, обновить Spreadsheet. Должен появиться пункт меню Avito -> Update Prices.
Выбираем его, даем нужные права и смотрим как заполняются цены в нашем документе.
PS Если в процессе произошла ошибка — в поиске причины помогут логи доступные из редактора скриптов Tools -> Script Editor -> View -> Logs.
Комментарии (31)
mihmig
02.08.2016 11:50+2Я так понимаю, данный вариант «парсинга! авито не приведёт к блокировке по IP — ну не будет же авито блокировать гугл!
Также могу предложить парсить мобильную версию сайта — там можно вытаскивать телефоны (этакая „метаинформация“ — можно определить различных „барыг“ и риэлтеров, маскирующихся по частных лиц.)ModoStudio
03.08.2016 10:32ну не будет же авито блокировать гугл!
А почему бы и нет! Авито нужна посещаемость и чтоб рекламу смотрели, а не подгружали всё через Гугл. Кстати, Гугл Докс уже использовали для DDoS, пока сам Гугл не прикрыл это дело.
garikbesson
02.08.2016 12:33-1var sheet = SpreadsheetApp.getActiveSheet(); var ss = SpreadsheetApp.getActiveSpreadsheet();
Не очень понятно, что Вы здесь делаете.
В "sheet" у вас хранится активная таблица. В "ss" — активный лист. А затем в активной таблице Вы ищете диапазон с именем "URL". Зачем его искать по всей таблице, если он у вас будет находиться только в активном листе.
То есть, если Вы хотели получить активную таблицу и в ней активный лист, то, на мой взгляд, это должно выглядеть следующим образом:
var sheet = SpreadsheetApp.getActiveSpreadsheet(); var ss = sheet.getActiveSheet();
И затем все манипуляции проводить уже с активным листом "ss".
LexB
02.08.2016 12:52+1В «sheet» у вас хранится активная таблица. В «ss» — активный лист.
Наоборот.
Документация — https://developers.google.com/apps-script/reference/spreadsheet/.
Все просто, getRangeByName есть только у Spreadsheet-а. У Sheet-а есть getNamedRanges() NamedRange[]. Можно перебрать циклом, но особого смысла нет.garikbesson
03.08.2016 09:12Хорошо, убедили)
Очень полезный метод getRangeByName, сам до него не добрался, поэтому благодарю за статью)
Anti-Dot
02.08.2016 13:24Немного не в тему вопрос, но возможно кто-то знает на него ответ…
Дело в том, что есть на авито — частники, а есть — магазины,
Так вот, по клику на магазин, можно сразу увидеть все объявления этого магазина
Вопрос в следующем: Как узнать все объявления, закреплённые за частником?
Спасибо.AVX
02.08.2016 14:41Подозреваю, что можно как-то сделать по номеру телефона, если судить по комментарию
XogN
03.08.2016 11:52Пользовался ли кто онлайн сервисами по мониторингу цен и товаров на Avito, которые отслеживают по заданным критериям поиска и автоматически уведомляют по e-mail? Одно время искал, приглянулся smartavito.ru. Но может что поинтереснее есть?
Scalar
Уметь писать скрипты в Spreadsheets, это полезно)
Но конкретно вашу задачу можно решить в два клика с помощью функции ImportXML
Она имеет свои ограничения, но здесь подходит
1. Правой кнопкой по цене, открываем веб инспектор на нужном элементе => Copy XPATH
2. В Spreadsheets пишем =IMPORTXML(URL, XPATH)
3. Profit
Вот небольшой пример
aavezel
т.е. если будет список из 500 объявлений, каждый раз, каждый зашедший человек будет загружать 500 страниц с авито?? :)
Scalar
Результат запроса кэшируется, так что все ссылки будут загружены по одному разу)
zulkas
А разве смысл скрипта в статье не в том чтобы отслеживать цены?
Если страницы закэшируются, то какой смысл в них если цены позже изменятся?
Scalar
Можно добавить параметр в URL, или просто ничего не делать, т.к. кэш живет не очень долго, около часа.
Если вам нужно чаще обновлять цены или другая сложная логика, то конечно такое простое решение здесь не подойдет.
ksider
а так http://elibrary.ru/ парсить нельзя?
у меня не получилось, что-то.