DHgate Affiliate Product Extractor

Extract product information with affiliate links and export to CSV

Size

13.7 KB

Version

1.1.1

Created

Nov 8, 2025

Updated

about 1 month ago

1// ==UserScript==
2// @name		DHgate Affiliate Product Extractor
3// @description		Extract product information with affiliate links and export to CSV
4// @version		1.1.1
5// @match		https://*.aff.dhgate.com/*
6// @icon		https://js.dhresource.com/dhgate/affiliate-publisher/favicon.ico
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('DHgate Affiliate Product Extractor loaded');
12
13    // Debounce function to prevent excessive calls
14    function debounce(func, wait) {
15        let timeout;
16        return function executedFunction(...args) {
17            const later = () => {
18                clearTimeout(timeout);
19                func(...args);
20            };
21            clearTimeout(timeout);
22            timeout = setTimeout(later, wait);
23        };
24    }
25
26    // Function to extract product data from the page
27    function extractProductData() {
28        console.log('Starting product extraction...');
29        const products = [];
30        
31        // Find all product items on the page
32        const productElements = document.querySelectorAll('.product-item[data-v-f70a41f0]');
33        console.log(`Found ${productElements.length} products`);
34        
35        productElements.forEach((product, index) => {
36            try {
37                // Extract product link
38                const linkElement = product.querySelector('a[data-v-f70a41f0][href]');
39                const productUrl = linkElement ? linkElement.getAttribute('href') : '';
40                
41                // Extract product title
42                const titleElement = product.querySelector('p.c-333.lh-20.ellipsis-two');
43                const title = titleElement ? titleElement.textContent.trim() : '';
44                
45                // Extract current price
46                const priceElement = product.querySelector('span.fs-14.f-b.main-color');
47                const price = priceElement ? priceElement.textContent.trim() : '';
48                
49                // Extract original price
50                const originalPriceElement = product.querySelector('span.c-999.td-lt');
51                const originalPrice = originalPriceElement ? originalPriceElement.textContent.trim() : '';
52                
53                // Extract commission
54                const commissionElement = product.querySelector('div.c-000.fs-14');
55                const commission = commissionElement ? commissionElement.textContent.trim() : '';
56                
57                // Extract commission rate
58                const rateElement = product.querySelector('div.c-999.mt-6.lh-16');
59                const rate = rateElement ? rateElement.textContent.trim() : '';
60                
61                // Extract coupon info if available
62                const couponElement = product.querySelector('.coupon span');
63                const coupon = couponElement ? couponElement.textContent.trim() : 'No coupon';
64                
65                // Extract image URL
66                const imageElement = product.querySelector('img[data-v-f70a41f0]');
67                const imageUrl = imageElement ? imageElement.getAttribute('src') || imageElement.getAttribute('data-src') : '';
68                
69                if (title && productUrl) {
70                    products.push({
71                        title,
72                        price,
73                        originalPrice,
74                        commission,
75                        rate,
76                        coupon,
77                        affiliateLink: productUrl,
78                        imageUrl
79                    });
80                    console.log(`Extracted product ${index + 1}: ${title}`);
81                }
82            } catch (error) {
83                console.error(`Error extracting product ${index + 1}:`, error);
84            }
85        });
86        
87        console.log(`Successfully extracted ${products.length} products`);
88        return products;
89    }
90
91    // Function to convert data to CSV format
92    function convertToCSV(products) {
93        if (products.length === 0) {
94            return '';
95        }
96        
97        // CSV headers
98        const headers = ['Title', 'Price', 'Original Price', 'Commission', 'Rate', 'Coupon', 'Affiliate Link', 'Image URL'];
99        
100        // Create CSV rows
101        const rows = products.map(product => {
102            return [
103                `"${product.title.replace(/"/g, '""')}"`,
104                `"${product.price}"`,
105                `"${product.originalPrice}"`,
106                `"${product.commission}"`,
107                `"${product.rate}"`,
108                `"${product.coupon}"`,
109                `"${product.affiliateLink}"`,
110                `"${product.imageUrl}"`
111            ].join(',');
112        });
113        
114        return [headers.join(','), ...rows].join('\n');
115    }
116
117    // Function to download CSV file
118    function downloadCSV(csvContent, filename) {
119        const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
120        const link = document.createElement('a');
121        const url = URL.createObjectURL(blob);
122        
123        link.setAttribute('href', url);
124        link.setAttribute('download', filename);
125        link.style.visibility = 'hidden';
126        
127        document.body.appendChild(link);
128        link.click();
129        document.body.removeChild(link);
130        
131        console.log(`CSV file "${filename}" downloaded successfully`);
132    }
133
134    // Function to export to Google Sheets
135    function exportToGoogleSheets(products) {
136        console.log('Exporting to Google Sheets...');
137        
138        // Create the data array with headers
139        const headers = ['Title', 'Price', 'Original Price', 'Commission', 'Rate', 'Coupon', 'Affiliate Link', 'Image URL'];
140        const rows = products.map(product => [
141            product.title,
142            product.price,
143            product.originalPrice,
144            product.commission,
145            product.rate,
146            product.coupon,
147            product.affiliateLink,
148            product.imageUrl
149        ]);
150        
151        const data = [headers, ...rows];
152        
153        // Convert to TSV format (Tab Separated Values) for Google Sheets
154        const tsvContent = data.map(row => row.join('\t')).join('\n');
155        
156        // Create a Google Sheets URL with the data
157        const encodedData = encodeURIComponent(tsvContent);
158        const sheetsUrl = 'https://docs.google.com/spreadsheets/create?usp=sheets_web#gid=0';
159        
160        // Copy data to clipboard
161        navigator.clipboard.writeText(tsvContent).then(() => {
162            console.log('Data copied to clipboard');
163            // Open Google Sheets in a new tab
164            window.open(sheetsUrl, '_blank');
165            alert('Data copied to clipboard! A new Google Sheet will open. Click on cell A1 and paste (Ctrl+V or Cmd+V) to import the data.');
166        }).catch(err => {
167            console.error('Failed to copy to clipboard:', err);
168            alert('Failed to copy data to clipboard. Please try the CSV export instead.');
169        });
170    }
171
172    // Function to create and show extraction button
173    function createExtractionButton() {
174        // Check if button already exists
175        if (document.getElementById('dhgate-extractor-btn')) {
176            console.log('Extraction button already exists');
177            return;
178        }
179        
180        // Find the search card area to place the button
181        const searchCard = document.querySelector('.search-card__top[data-v-57e1c60a]');
182        if (!searchCard) {
183            console.log('Search card not found, will retry...');
184            return;
185        }
186        
187        // Create button container
188        const buttonContainer = document.createElement('div');
189        buttonContainer.id = 'dhgate-extractor-btn';
190        buttonContainer.style.cssText = `
191            margin-left: 16px;
192            display: inline-flex;
193            gap: 8px;
194            align-items: center;
195        `;
196        
197        // Create the CSV export button
198        const extractButton = document.createElement('button');
199        extractButton.textContent = '📊 Export to CSV';
200        extractButton.style.cssText = `
201            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
202            color: white;
203            border: none;
204            padding: 8px 20px;
205            font-size: 14px;
206            font-weight: 600;
207            border-radius: 4px;
208            cursor: pointer;
209            transition: all 0.3s ease;
210            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
211        `;
212        
213        // Create the Google Sheets export button
214        const sheetsButton = document.createElement('button');
215        sheetsButton.textContent = '📗 Export to Google Sheets';
216        sheetsButton.style.cssText = `
217            background: linear-gradient(135deg, #34a853 0%, #0f9d58 100%);
218            color: white;
219            border: none;
220            padding: 8px 20px;
221            font-size: 14px;
222            font-weight: 600;
223            border-radius: 4px;
224            cursor: pointer;
225            transition: all 0.3s ease;
226            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
227        `;
228        
229        // Add hover effect for CSV button
230        extractButton.addEventListener('mouseenter', () => {
231            extractButton.style.transform = 'translateY(-2px)';
232            extractButton.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
233        });
234        
235        extractButton.addEventListener('mouseleave', () => {
236            extractButton.style.transform = 'translateY(0)';
237            extractButton.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
238        });
239        
240        // Add hover effect for Sheets button
241        sheetsButton.addEventListener('mouseenter', () => {
242            sheetsButton.style.transform = 'translateY(-2px)';
243            sheetsButton.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
244        });
245        
246        sheetsButton.addEventListener('mouseleave', () => {
247            sheetsButton.style.transform = 'translateY(0)';
248            sheetsButton.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
249        });
250        
251        // Add click handler for CSV export
252        extractButton.addEventListener('click', () => {
253            console.log('CSV Export button clicked');
254            extractButton.textContent = '⏳ Extracting...';
255            extractButton.disabled = true;
256            
257            setTimeout(() => {
258                const products = extractProductData();
259                
260                if (products.length === 0) {
261                    alert('No products found on this page. Please make sure you are on a product listing page.');
262                    extractButton.textContent = '📊 Export to CSV';
263                    extractButton.disabled = false;
264                    return;
265                }
266                
267                const csvContent = convertToCSV(products);
268                const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
269                const filename = `dhgate-products-${timestamp}.csv`;
270                
271                downloadCSV(csvContent, filename);
272                
273                extractButton.textContent = `✅ Exported ${products.length} Products`;
274                
275                setTimeout(() => {
276                    extractButton.textContent = '📊 Export to CSV';
277                    extractButton.disabled = false;
278                }, 2000);
279            }, 100);
280        });
281        
282        // Add click handler for Google Sheets export
283        sheetsButton.addEventListener('click', () => {
284            console.log('Google Sheets Export button clicked');
285            sheetsButton.textContent = '⏳ Extracting...';
286            sheetsButton.disabled = true;
287            
288            setTimeout(() => {
289                const products = extractProductData();
290                
291                if (products.length === 0) {
292                    alert('No products found on this page. Please make sure you are on a product listing page.');
293                    sheetsButton.textContent = '📗 Export to Google Sheets';
294                    sheetsButton.disabled = false;
295                    return;
296                }
297                
298                exportToGoogleSheets(products);
299                
300                sheetsButton.textContent = `✅ Exported ${products.length} Products`;
301                
302                setTimeout(() => {
303                    sheetsButton.textContent = '📗 Export to Google Sheets';
304                    sheetsButton.disabled = false;
305                }, 3000);
306            }, 100);
307        });
308        
309        buttonContainer.appendChild(extractButton);
310        buttonContainer.appendChild(sheetsButton);
311        
312        // Insert button next to the search area
313        const topSection = searchCard.querySelector('.mb-32.v-center.jc-sb');
314        if (topSection) {
315            const leftSection = topSection.querySelector('.v-center');
316            if (leftSection) {
317                leftSection.appendChild(buttonContainer);
318                console.log('Extraction button created successfully');
319            }
320        }
321    }
322
323    // Initialize the extension
324    function init() {
325        console.log('Initializing DHgate Affiliate Product Extractor...');
326        
327        // Wait for the page to load
328        if (document.readyState === 'loading') {
329            document.addEventListener('DOMContentLoaded', init);
330            return;
331        }
332        
333        // Try to create button immediately
334        createExtractionButton();
335        
336        // Use MutationObserver to handle dynamic content loading
337        const observer = new MutationObserver(debounce(() => {
338            createExtractionButton();
339        }, 500));
340        
341        observer.observe(document.body, {
342            childList: true,
343            subtree: true
344        });
345        
346        // Also retry after a delay in case content loads slowly
347        setTimeout(createExtractionButton, 2000);
348        setTimeout(createExtractionButton, 4000);
349    }
350
351    // Start the extension
352    init();
353})();
DHgate Affiliate Product Extractor | Robomonkey