将 Qoo10 的商品列表.xlsx 中的相册按SKU命名文件夹现在下载到本地
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. const XLSX = require('xlsx');
  2. const axios = require('axios');
  3. const path = require('path');
  4. const url = require('url');
  5. const fs = require('fs').promises;
  6. const { existsSync, mkdirSync } = require('fs');
  7. // 获取文件名从URL
  8. function getFilenameFromUrl(urlString) {
  9. try {
  10. const parsed = new URL(urlString);
  11. let filename = path.basename(parsed.pathname);
  12. // 如果文件名为空或无效,生成时间戳文件名
  13. if (!filename || !filename.includes('.')) {
  14. const timestamp = Date.now();
  15. filename = `image_${timestamp}.jpg`;
  16. }
  17. return filename;
  18. } catch (error) {
  19. console.error(`Error parsing URL ${urlString}: ${error.message}`);
  20. const timestamp = Date.now();
  21. return `image_${timestamp}.jpg`;
  22. }
  23. }
  24. // 下载图片
  25. async function downloadImage(imageUrl, outputPath) {
  26. try {
  27. const response = await axios({
  28. method: 'GET',
  29. url: imageUrl,
  30. responseType: 'arraybuffer'
  31. });
  32. await fs.writeFile(outputPath, response.data);
  33. console.log(`Downloaded: ${outputPath}`);
  34. } catch (error) {
  35. console.error(`Error downloading image ${imageUrl}: ${error.message}`);
  36. }
  37. }
  38. // 处理Excel文件
  39. async function processExcel() {
  40. try {
  41. // 获取当前目录下的第一个xlsx文件
  42. const files = await fs.readdir('.');
  43. const xlsxFile = files.find(file => file.endsWith('.xlsx'));
  44. if (!xlsxFile) {
  45. console.log("No xlsx file found in current directory");
  46. return;
  47. }
  48. // 读取Excel文件
  49. const workbook = XLSX.readFile(xlsxFile);
  50. const worksheet = workbook.Sheets[workbook.SheetNames[0]];
  51. // 转换为JSON,跳过前4行
  52. const data = XLSX.utils.sheet_to_json(worksheet, {
  53. header: 1,
  54. range: 4 // 从第5行开始 (0-based index)
  55. });
  56. // 处理每一行
  57. for (const row of data) {
  58. if (!row[1]) continue; // B列为空则跳过
  59. const folderName = row[1].toString().trim();
  60. const imageUrl1 = row[17]; // R列
  61. const imageUrl2 = row[18]; // S列
  62. if (!folderName) continue;
  63. // 创建文件夹
  64. const folderPath = `./goods/${folderName}`;
  65. if (!existsSync(folderPath)) {
  66. mkdirSync(folderPath, { recursive: true });
  67. }
  68. // 创建Details子文件夹
  69. const detailsPath = path.join(folderPath, 'details');
  70. if (!existsSync(detailsPath)) {
  71. mkdirSync(detailsPath, { recursive: true });
  72. }
  73. // 下载R列图片
  74. if (imageUrl1) {
  75. const filename1 = getFilenameFromUrl(imageUrl1);
  76. await downloadImage(imageUrl1, path.join(folderPath, filename1));
  77. }
  78. // 下载S列的多个图片
  79. if (imageUrl2) {
  80. const imageUrls = imageUrl2.split('$$').filter(url => url.trim());
  81. for (let i = 0; i < imageUrls.length; i++) {
  82. const imageUrl = imageUrls[i].trim();
  83. if (imageUrl) {
  84. const filename = getFilenameFromUrl(imageUrl);
  85. await downloadImage(imageUrl, path.join(detailsPath, filename));
  86. }
  87. }
  88. }
  89. }
  90. console.log("Processing completed!");
  91. } catch (error) {
  92. console.error(`Error processing Excel file: ${error.message}`);
  93. }
  94. }
  95. // 运行程序
  96. processExcel().catch(console.error);