|
1 | 1 | // DHL Geschäftskundenportal Invoices Download - Puppeteer script that logs in, filters invoices for the previous month, and extracts their details for download |
2 | 2 | // Last update: 2025-10-03 |
3 | 3 |
|
4 | | - |
5 | 4 | const puppeteer = require("puppeteer"); |
6 | 5 |
|
7 | 6 | // Settings |
8 | 7 | const username = $env.DHL_USERNAME; |
9 | 8 | const password = $env.DHL_PASSWORD; |
10 | 9 |
|
11 | | - |
12 | 10 | // Define an async function to contain all your await calls |
13 | 11 | async function dhlGeschaftskundenportalInvoicesDownload() { |
14 | | - const browser = await puppeteer.launch({ |
15 | | - headless: false, |
16 | | - args: ["--no-sandbox", "--disable-setuid-sandbox", "--start-fullscreen"], |
17 | | - }); |
18 | | - |
19 | | - const page = await browser.newPage(); |
20 | | - |
21 | | - // Settings |
22 | | - await page.setViewport({ width: 1920, height: 1080 }); |
23 | | - await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"); |
24 | | - // page.on('console', msg => console.log('BROWSER CONSOLE:', msg.text())); |
25 | | - |
26 | | - // Navigate to login page |
27 | | - await page.goto("https://geschaeftskunden.dhl.de"); |
28 | | - |
29 | | - // Cookies |
30 | | - await page.waitForSelector("#onetrust-reject-all-handler", { visible: true, timeout: 5000 }).catch((e) => { |
31 | | - console.log("Cookie consent button not found or already gone."); |
| 12 | + const browser = await puppeteer.launch({ |
| 13 | + headless: false, |
| 14 | + args: ["--no-sandbox", "--disable-setuid-sandbox", "--start-fullscreen"], |
| 15 | + }); |
| 16 | + |
| 17 | + const page = await browser.newPage(); |
| 18 | + |
| 19 | + // Settings |
| 20 | + await page.setViewport({ width: 1920, height: 1080 }); |
| 21 | + await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"); |
| 22 | + // page.on('console', msg => console.log('BROWSER CONSOLE:', msg.text())); |
| 23 | + |
| 24 | + // Navigate to login page |
| 25 | + await page.goto("https://geschaeftskunden.dhl.de"); |
| 26 | + |
| 27 | + // Cookies |
| 28 | + await page |
| 29 | + .waitForSelector("#onetrust-reject-all-handler", { |
| 30 | + visible: true, |
| 31 | + timeout: 5000, |
| 32 | + }) |
| 33 | + .catch((e) => { |
| 34 | + console.log("Cookie consent button not found or already gone."); |
32 | 35 | }); |
33 | | - if (await page.$("#onetrust-reject-all-handler")) { |
34 | | - await page.click("#onetrust-reject-all-handler"); |
35 | | - await page.waitForNavigation(); |
36 | | - } |
37 | | - |
38 | | - // "Anmelden" |
39 | | - await page.waitForSelector("#button-noName", { visible: true }); |
40 | | - await page.click("#button-noName"); |
41 | | - |
42 | | - // Fill in credentials |
43 | | - await page.waitForSelector("#username", { visible: true, timeout: 10000 }); |
44 | | - await page.type("#username", username); |
45 | | - await page.type("#password", password); |
46 | | - |
47 | | - // Login |
48 | | - await page.click('button[type="submit"]'); |
| 36 | + if (await page.$("#onetrust-reject-all-handler")) { |
| 37 | + await page.click("#onetrust-reject-all-handler"); |
49 | 38 | await page.waitForNavigation(); |
50 | | - |
51 | | - // Navigate to invoice section |
52 | | - await page.goto("https://geschaeftskunden.dhl.de/billing/invoice/overview"); |
53 | | - |
54 | | - // Display "Last 3 months" invoices |
55 | | - await page.waitForSelector('[data-testid="date-range-input-field-function-icon-billingView-filter-dateRange"]'); |
56 | | - await page.click('[data-testid="date-range-input-field-function-icon-billingView-filter-dateRange"]'); |
57 | | - const presetDropdownSelector = '[data-testid="billingView-filter-dateRange-footer-presetRangeSelector"]'; |
58 | | - await page.waitForSelector(presetDropdownSelector, { visible: true }); |
59 | | - await page.select(presetDropdownSelector, "1"); |
60 | | - const submitButtonSelector = '[data-testid="billingView-filter-dateRange-footer-submit"]'; |
61 | | - await page.waitForSelector(submitButtonSelector, { visible: true, timeout: 5000 }); |
62 | | - await page.click(submitButtonSelector); |
63 | | - |
64 | | - // Define the month and year for the previous month |
65 | | - const today = new Date(); |
66 | | - const targetDate = new Date(today.getFullYear(), today.getMonth() - 1, 1); |
67 | | - const targetMonth = targetDate.getMonth(); |
68 | | - const targetYear = targetDate.getFullYear(); |
69 | | - |
70 | | - // Get invoices details |
71 | | - await page.waitForSelector('table[data-testid="billingView"] tbody > tr.dhlTable-row-default', { visible: true, timeout: 10000 }); |
72 | | - |
73 | | - const invoices = await page.evaluate( |
74 | | - (month, year) => { |
75 | | - const table = document.querySelector('table[data-testid="billingView"]'); |
76 | | - const rows = Array.from(table.querySelectorAll("tbody > tr.dhlTable-row-default")); |
77 | | - const data = []; |
78 | | - |
79 | | - for (const row of rows) { |
80 | | - const dateCell = row.querySelector(".dhlTablecell:nth-child(2)"); |
81 | | - const invoiceNumberCell = row.querySelector(".dhlTablecell:nth-child(3)"); |
82 | | - const descriptionCell = row.querySelector(".dhlTablecell:nth-child(4)"); |
83 | | - const amountCell = row.querySelector(".dhlTablecell:nth-child(5)"); |
84 | | - |
85 | | - if (dateCell && invoiceNumberCell && descriptionCell && amountCell) { |
86 | | - const dateText = dateCell.textContent.trim(); |
87 | | - const parts = dateText.split("."); |
88 | | - const invoiceMonth = parseInt(parts[1], 10) - 1; |
89 | | - const invoiceYear = parseInt(parts[2], 10); |
90 | | - |
91 | | - if (invoiceMonth === month && invoiceYear === year) { |
92 | | - const invoiceNumber = invoiceNumberCell.textContent.trim(); |
93 | | - const invoiceDescription = descriptionCell.textContent.trim(); |
94 | | - const invoiceAmount = amountCell.textContent.trim(); |
95 | | - |
96 | | - const downloadButton = row.querySelector("td .svgIcon-pdf").closest("button"); |
97 | | - const buttonId = downloadButton ? downloadButton.id : null; |
98 | | - |
99 | | - data.push({ |
100 | | - date: dateText, |
101 | | - invoiceNumber: invoiceNumber, |
102 | | - description: invoiceDescription, |
103 | | - amount: invoiceAmount, |
104 | | - buttonId: buttonId, |
105 | | - }); |
106 | | - } |
107 | | - } |
108 | | - } |
109 | | - return data; |
110 | | - }, |
111 | | - targetMonth, |
112 | | - targetYear |
113 | | - ); |
114 | | - |
115 | | - console.log("Filtered Invoices for Last Month:", invoices); |
116 | | - |
117 | | - // Close browser |
118 | | - await browser.close(); |
119 | | - |
120 | | - return invoices.map((invoice) => ({ |
121 | | - json: { |
122 | | - date: invoice.dateText, |
123 | | - invoiceNumber: invoice.invoiceNumber, |
124 | | - description: invoice.description, |
125 | | - amount: invoice.amount, |
126 | | - buttonId: invoice.buttonId, |
127 | | - }, |
128 | | - })); |
| 39 | + } |
| 40 | + |
| 41 | + // "Anmelden" |
| 42 | + await page.waitForSelector("#button-noName", { visible: true }); |
| 43 | + await page.click("#button-noName"); |
| 44 | + |
| 45 | + // Fill in credentials |
| 46 | + await page.waitForSelector("#username", { visible: true, timeout: 10000 }); |
| 47 | + await page.type("#username", username); |
| 48 | + await page.type("#password", password); |
| 49 | + |
| 50 | + // Login |
| 51 | + await page.click('button[type="submit"]'); |
| 52 | + await page.waitForNavigation(); |
| 53 | + |
| 54 | + // Navigate to invoice section |
| 55 | + await page.goto("https://geschaeftskunden.dhl.de/billing/invoice/overview"); |
| 56 | + |
| 57 | + // Display "Last 3 months" invoices |
| 58 | + await page.waitForSelector('[data-testid="date-range-input-field-function-icon-billingView-filter-dateRange"]'); |
| 59 | + await page.click('[data-testid="date-range-input-field-function-icon-billingView-filter-dateRange"]'); |
| 60 | + const presetDropdownSelector = '[data-testid="billingView-filter-dateRange-footer-presetRangeSelector"]'; |
| 61 | + await page.waitForSelector(presetDropdownSelector, { visible: true }); |
| 62 | + await page.select(presetDropdownSelector, "1"); |
| 63 | + const submitButtonSelector = '[data-testid="billingView-filter-dateRange-footer-submit"]'; |
| 64 | + await page.waitForSelector(submitButtonSelector, { |
| 65 | + visible: true, |
| 66 | + timeout: 5000, |
| 67 | + }); |
| 68 | + await page.click(submitButtonSelector); |
| 69 | + |
| 70 | + // Define the month and year for the previous month |
| 71 | + const today = new Date(); |
| 72 | + const targetDate = new Date(today.getFullYear(), today.getMonth() - 1, 1); |
| 73 | + const targetMonth = targetDate.getMonth(); |
| 74 | + const targetYear = targetDate.getFullYear(); |
| 75 | + |
| 76 | + // Get invoices details |
| 77 | + await page.waitForSelector('table[data-testid="billingView"] tbody > tr.dhlTable-row-default', { visible: true, timeout: 10000 }); |
| 78 | + |
| 79 | + const invoices = await page.evaluate( |
| 80 | + (month, year) => { |
| 81 | + const table = document.querySelector('table[data-testid="billingView"]'); |
| 82 | + const rows = Array.from(table.querySelectorAll("tbody > tr.dhlTable-row-default")); |
| 83 | + const data = []; |
| 84 | + |
| 85 | + for (const row of rows) { |
| 86 | + const dateCell = row.querySelector(".dhlTablecell:nth-child(2)"); |
| 87 | + const invoiceNumberCell = row.querySelector(".dhlTablecell:nth-child(3)"); |
| 88 | + const descriptionCell = row.querySelector(".dhlTablecell:nth-child(4)"); |
| 89 | + const amountCell = row.querySelector(".dhlTablecell:nth-child(5)"); |
| 90 | + |
| 91 | + if (dateCell && invoiceNumberCell && descriptionCell && amountCell) { |
| 92 | + const dateText = dateCell.textContent.trim(); |
| 93 | + const parts = dateText.split("."); |
| 94 | + const invoiceMonth = parseInt(parts[1], 10) - 1; |
| 95 | + const invoiceYear = parseInt(parts[2], 10); |
| 96 | + |
| 97 | + if (invoiceMonth === month && invoiceYear === year) { |
| 98 | + const invoiceNumber = invoiceNumberCell.textContent.trim(); |
| 99 | + const invoiceDescription = descriptionCell.textContent.trim(); |
| 100 | + const invoiceAmount = amountCell.textContent.trim(); |
| 101 | + |
| 102 | + const downloadButton = row.querySelector("td .svgIcon-pdf").closest("button"); |
| 103 | + const buttonId = downloadButton ? downloadButton.id : null; |
| 104 | + |
| 105 | + data.push({ |
| 106 | + date: dateText, |
| 107 | + invoiceNumber: invoiceNumber, |
| 108 | + description: invoiceDescription, |
| 109 | + amount: invoiceAmount, |
| 110 | + buttonId: buttonId, |
| 111 | + }); |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + return data; |
| 116 | + }, |
| 117 | + targetMonth, |
| 118 | + targetYear, |
| 119 | + ); |
| 120 | + |
| 121 | + console.log("Filtered Invoices for Last Month:", invoices); |
| 122 | + |
| 123 | + // Close browser |
| 124 | + await browser.close(); |
| 125 | + |
| 126 | + return invoices.map((invoice) => ({ |
| 127 | + json: { |
| 128 | + date: invoice.dateText, |
| 129 | + invoiceNumber: invoice.invoiceNumber, |
| 130 | + description: invoice.description, |
| 131 | + amount: invoice.amount, |
| 132 | + buttonId: invoice.buttonId, |
| 133 | + }, |
| 134 | + })); |
129 | 135 | } |
130 | 136 |
|
131 | 137 | dhlGeschaftskundenportalInvoicesDownload().catch(console.error); |
0 commit comments