-
Notifications
You must be signed in to change notification settings - Fork 0
/
zomato.js
119 lines (91 loc) · 3.71 KB
/
zomato.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
const puppeteer = require('puppeteer');
const USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0';
const LANGUAGE_HEADERS = {
'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8',
};
const ZOMATO_BASE_URL = 'https://www.zomato.com';
const LOG_IN_BUTTON_SELECTOR_ONE = '#signin-link';
const LOG_IN_BUTTON_SELECTOR_TWO = '#login-email';
const USERNAME_SELECTOR = '#ld-email';
const PASSWORD_SELECTOR = '#ld-password';
const LOG_IN_SUBMIT_BUTTON = '#ld-submit-global';
const ORDER_SELECTOR = '.order-history-snippet';
const RESTAURANT_SELECTOR = 'div.nowrap';
const COST_SELECTOR = '.cost';
const DATE_SELECTOR = 'div.ui.basic.label';
const STATUS_SELECTOR = '.right.floated';
const DROPDOWN_OPTIONS_SELECTOR = 'a.item';
const LOAD_MORE_SELECTOR = '#order-history-load-more > button:nth-child(1)';
const randomDelay = async (page, seconds) => page.waitFor(Math.random() * seconds * 1000);
const inputText = async (page, selector, text) => {
await randomDelay(page, 2);
await page.click(selector);
await page.keyboard.type(text);
};
const trimedInnerText = el => el.innerText.trim();
const getCost = async order => order.$eval(COST_SELECTOR, it => parseFloat(it.innerText.slice(1)).toFixed(2));
const getDate = async order => order.$eval(DATE_SELECTOR, trimedInnerText);
const getRestaurant = async order => order.$eval(RESTAURANT_SELECTOR, trimedInnerText);
const getStatus = async order => order.$eval(STATUS_SELECTOR, trimedInnerText);
const extractOrderDetails = async order => ({
cost: await getCost(order),
date: await getDate(order),
restaurant: await getRestaurant(order),
status: await getStatus(order),
});
async function loginToZomato(page, { emailID, password }) {
await page.goto(ZOMATO_BASE_URL, {
waitUntil: 'networkidle2',
});
await page.click(LOG_IN_BUTTON_SELECTOR_ONE);
await page.waitForSelector(LOG_IN_BUTTON_SELECTOR_TWO);
await page.click(LOG_IN_BUTTON_SELECTOR_TWO);
await inputText(page, USERNAME_SELECTOR, emailID);
await inputText(page, PASSWORD_SELECTOR, password);
await page.click(LOG_IN_SUBMIT_BUTTON);
}
async function extractProfileID(page) {
const profileUrls = await page.$$eval(DROPDOWN_OPTIONS_SELECTOR, links => links
.map(link => link.href)
.filter(url => url.startsWith('https://www.zomato.com/users/')));
if (!Array.isArray(profileUrls) || profileUrls.length === 0) {
throw new Error('No profile links were found!');
}
return profileUrls[0].replace('https://www.zomato.com/users/', '').split('/')[0];
}
async function scrollToBottom(page) {
while (true) {
try {
await page.click(LOAD_MORE_SELECTOR);
await page.waitForSelector(LOAD_MORE_SELECTOR, { visible: true, timeout: 5000 });
await randomDelay(page, 5);
} catch (e) {
if (e.name === 'TimeoutError') {
console.log(e);
}
break;
}
}
}
async function scrapeZomatoOrders({ emailID, password }) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setUserAgent(USER_AGENT);
await page.setExtraHTTPHeaders(LANGUAGE_HEADERS);
await loginToZomato(page, { emailID, password });
await randomDelay(page, 5);
const profileID = await extractProfileID(page);
// console.log(`Profile ID: ${profileID}`)
const ORDERS_PAGE_URL = `https://www.zomato.com/users/${profileID}/ordering`;
await page.goto(ORDERS_PAGE_URL, {
waitUntil: 'networkidle2',
});
await scrollToBottom(page);
// const orders = await extractOrders(page);
const orderDetails = await page.$$(ORDER_SELECTOR)
.then(orders => Promise.all(orders.map(async order => extractOrderDetails(order))));
await page.close();
await browser.close();
return orderDetails;
}
module.exports = scrapeZomatoOrders;