Кукла Является ли библиотека JavaScript/Nodejs, которая прилагает инструменты Google Chrome или Chromium Browers с использованием протокола Chrome devtools. Подумайте об этом как о способе написать JavaScript для управления каждым аспектом браузера Chrome. Я написал статью Начало работы с quippeeter Это проходило через процесс загрузки приложения js/ucpeteeter js/uppeteer и повернув веб-страницу в запрос на запрос API с помощью quipeteer.
Я изначально заинтересовался кукловолом, потому что у меня было неэффективность в моей повседневной жизни. Одним из тех недействительных были на том, насколько утомительно и монотонный продуктовый магазин. Кукольщик был инструментальным в этом стремлении.
За что это стоит, покупки продуктов не так уж плохо. Это может Будьте вроде сумасшедшие, когда молодые дети помечены вместе. Groceryjs имеет дополнительное преимущество того, чтобы быть интересным техническим заданием, поэтому здесь мы.
Ломать покупки продуктов
Шоппинг для продуктов – это процессуальная деятельность:
- Вы просматриваете свой холодильник и кладовую для вещей, которые вам нужны и сделайте список
- Ты ходишь, велосипед или езжай в магазин
- Вы идете по проходам, добавляя вещи в вашу корзину, когда вы их видите
- Наконец вы платите и принесите свои продукты продуктов
Этот процесс имеет тенденцию происходить каждую неделю или два, для крупных заказа на продуктовые продукты.
Перевод этого в компьютерную программу основные действия:
- Читать элементы из списка
- Поиск и добавьте элементы в корзину
- Подготовьте тележку для оформления заказа и оформления заказа
С этим в виду, я построил Groceryjs.
Ломать скрипт
Groceryjs разбиты на несколько кусков кода после большого количества экспериментов:
Источник
Источник – это бэкэнда данных, именно здесь проводится продуктовый список. Это также место проведения для результатов продовольствия продовольствия. Для, Groceryjs, я начал с файла текста (YAML), затем переходил на лист Google. Я нашел лист Google, чтобы быть то, что доступно из повсюду, настольного компьютера и мобильного телефона, не требуя куча пользовательского интерфейса. Google предоставляет довольно надежный набор библиотек Nodejs, вы можете использовать для взаимодействия с дисками Google и APIS.
Мой продуктовый список хранится в первых 2 столбцах и первых 50 рядах (произвольных) в первом листе.
Листы-продукты-Source.js
Имеет два основных действия после инициализации нескольких объектов.
Первый получает список продуктов, GetGroceryList ()
Отказ
async getGroceryList() { let spreadsheetId = this._spreadsheetId; let sheetsService = this._sheetsService; return await new Promise((resolve, reject) => { sheetsService.spreadsheets.values.get({ spreadsheetId: spreadsheetId, range: 'A1:C50' }, (err, result) => { if (err) { reject(err); } else if (result && result.data && result.data.values) { let items = []; for (let i = 1; i < result.data.values.length; i++) { let value = result.data.values[i]; items.push({ name: value[0], quantity: value[1] }); } resolve(items); } else { resolve([]); } }); }); }
Второе добавляет результаты определенных покупок к листу, addshoppingresults. ()
.
async addShoppingResults(title, sheetId, results) { let sheetsService = this._sheetsService; let spreadsheetId = this._spreadsheetId; return new Promise((resolve, reject) => { let requests = []; let idx = 1; // convert results to an array we can write let data = []; let headers = [ { userEnteredValue: { stringValue: 'Requested' } }, { userEnteredValue: { stringValue: 'Item' } }, { userEnteredValue: { stringValue: 'Price' } }, ]; data.push({ values: headers }); for (let i = 0; i < results.length; i++) { let result = results[i]; let row = []; row.push({ userEnteredValue: { stringValue: result.requested } }); if (result.result) { row.push({ userEnteredValue: { stringValue: result.result.title } }); row.push({ userEnteredValue: { numberValue: result.result.price } }); } data.push({ values: row }); } // add the sheet requests.push({ addSheet: { /* removed for brevity's sake */ } }); // updateCells request requests.push({ /* removed for brevity's sake */ }); // auto size things requests.push({ /* removed for brevity's sake */ }); // execute the batch update sheetsService.spreadsheets.batchUpdate({ spreadsheetId: spreadsheetId, resource: { requests: requests } }, (err, result) => { if (err) { reject(err); } else { resolve(`https://docs.google.com/spreadsheets/d/${spreadsheetId}/edit#gid=${sheetId}`); } }); }); }
Покупатель
Покупатель содержит весь код и действия, которые составляют успешную поездку в продуктовый магазин. Он построен на вершине коммунальной библиотеки, которую я написал под названием Puppet-Helper.js
Отказ
Кукольный помощник
Кукольный помощник содержит все вещи, необходимые для взаимодействия с современным веб-приложением, например, нажав кнопку, учитывая селектор CSS:
async clickButton(selector, clickCount = 1) { this.assertPageOpen(); let button = await this._page.$(selector); if (button) { await button.click({ clickCount: clickCount }); } else { throw new Error(`Unable to click ${selector}`); } }
Или получение текста из элемента HTML:
async getTextFromElement(element) { this.assertPageOpen(); return await this._page.evaluate(el => el.innerText, element); }
Как вы можете себе представить, вы можете строгать достаточно этих действий вместе, чтобы имитировать пользователя, покупки продуктов онлайн.
Дорожный покупатель
Все больше и больше продуктовых магазинов предлагают интернет-магазины в Интернете, позволяя клиентам удобство покупки с их компьютера, планшета или мобильного телефона. Мы покупаем на продуктах LOWES, цепочке продуктового магазина на бакуляции в Северной Каролине. Noines Foods предлагает интернет-магазин, Lowes Foods Go Отказ За 49-19 долл. США ежегодно (или от 4 до 5 долларов за заказ), вы можете заказать продукты, используя их веб-приложение. После того, как вы разместите свой заказ, сотрудник Lowes Foods будет делать покупки вашего заказа и позвонить вам, когда они закончат (или если у них есть какие-либо вопросы). Когда заказ завершен, вы можете забрать его или доставляло его.
DAD/MOM-HACK, Магазин для продуктов онлайн, если вы можете помочь. Принимая молодых детей в продуктовый магазин. 😅
Я провел много времени, изучающий интерфейсный код для Lowes Foods, чтобы пойти. Я решил, что это Угловой На основании прогрессивного веб-приложения. Он очень хорошо поддается автоматизации с кукловом. Использование Puppet-Helper.js.
Я могу нарисовать несколько методов, чтобы получить несколько вещей.
Поиск продуктов
async searchImpl(query) { this._logger.info(`Searching for ${query}`); let productDivs = null; await this._puppetHelper.clearText('#search-nav-input'); await this._puppetHelper.enterText('#search-nav-input', query); await this._puppetHelper.wait(SHORT); await this._puppetHelper.clickButton('#search-nav-search'); await this._puppetHelper.wait(MID); // body > div:nth-child(5) > div > div > div.content-wrapper > div > lazy-load > ol let resultsDiv = await this._puppetHelper.getElement('ol.cell-container'); if (resultsDiv) { productDivs = await this._puppetHelper.getElementsFromParent(resultsDiv, '.cell.product-cell'); } return productDivs; }
Вход в систему
async login(email, password) { this._logger.info(`Logging into account ${email}...`); await this._puppetHelper.goToUrl(SHOPPING_URL); await this._puppetHelper.clickButton('#loyalty-onboarding-dismiss'); await this._puppetHelper.wait(SHORT); await this._puppetHelper.clickButton('#shopping-selector-parent-process-modal-close-click'); await this._puppetHelper.wait(SHORT); await this._puppetHelper.clickButton('#nav-register'); await this._puppetHelper.wait(SHORT) await this._puppetHelper.enterText('#login-email', email); await this._puppetHelper.wait(SHORT) await this._puppetHelper.enterText('#login-password', password); await this._puppetHelper.wait(SHORT) await this._puppetHelper.clickButton('#login-submit'); await this._puppetHelper.wait(XLONG); }
Показывая и опорожнять вашу корзину
async showCart() { this._logger.info(`Opening the shopping cart...`); await this._puppetHelper.clickButton('#nav-cart-main-checkout-cart'); await this._puppetHelper.wait(MID); } async emptyCart() { this._logger.info(`Emptying cart...`); await this.showCart(); await this._puppetHelper.clickButton('#checkout-cart-empty'); await this._puppetHelper.wait(NANO); await this._puppetHelper.clickButton('#error-modal-ok-button'); await this._puppetHelper.wait(MINI); }
Положить его вместе
Со всеми упомянутыми деталями я могу иметь Groceryjs, подготовит корзину, полную продуктов. Когда это сделано, он отправляет мне электронное письмо со ссылкой на корзину (чтобы я мог бы быстро оформить заказ) и ссылку на лист Google для целей отслеживания.
(async () => { let shopper = null; try { let sheetSource = new SheetGrocerySource(logger, credential.client_email, credential.private_key, config.source.sheetId); await sheetSource.init(); let list = await sheetSource.getGroceryList(); // login and create a blank slate to shop shopper = new LowesShopper(logger); await shopper.init(config.shopper.headless); await shopper.login(config.shopper.email, config.shopper.password); await shopper.emptyCart(); // do the shoppping let shoppingResults = []; for (let i = 0; i < list.length; i++) { let requestedItem = list[i]; let shoppedItem = await shopper.addItemToCart(requestedItem.name, requestedItem.quantity); shoppingResults.push({ requested: requestedItem.name, result: shoppedItem }); } // notify let dateStr = moment().format('MMMM Do YYYY @ h:mm a'); let title = `Shopping Trip on ${dateStr}`; let urlToCart = 'https://shop.lowesfoods.com/checkout/cart'; let urlToSheet = await sheetSource.addShoppingResults(title, moment().unix(), shoppingResults); let emailBody = ` Shopping Cart: ${urlToCart}
Shopping Results: ${urlToSheet}`; let mailOptions = { service: config.email.sender.service, user: config.email.sender.email, password: config.email.sender.appPassword }; mailUtil.sendEmail(config.email.recipeint.sender, config.email.recipeint.email, title, emailBody, mailOptions); } catch (e) { logger.error('Error while shopping', e); } finally { if (shopper) { await shopper.shutdown(); } } })();
Заключение
Итак, это все. Groceryjs еще не закончен. Настоящая работа на самом деле в деталях, таких как алгоритм для добавления продуктов из результатов поиска в вашу корзину. Lowes Foods, чтобы пойти, имеет собственный алгоритм поиска для определения актуальности результата к поиску. Во многих случаях их алгоритм не будет соответствовать ожиданиям, но может быть дополнено:
- Если Groceryjs предпочитают продукты, которые на продажу?
- Если Groceryjs предпочитают продукты для конкретной марки?
- Если Groceryjs предпочитают продукты, которые я купил раньше?
Есть тонна расчетов, которые мы делаем каждый раз, когда мы продували магазин, что я не осознавал, пока не начал работать на Groceryjs.
Нажмите репозиторий GitHUB для всего исходного кода. Обязательно прочитайте файл Readme, прежде чем прыгать.
github.com/emuneee/groceryjs
Я действительно заинтересован в том, чтобы услышать, что интересные люди используют кукольщик.
Оригинал: “https://dev.to/evanhalley/groceryjs-javascript-your-groceries-1j3d”