Created
November 1, 2020 04:16
-
-
Save antiops/2d6fcf7a78111e09aefad45eeaaa5e21 to your computer and use it in GitHub Desktop.
pixieset.com dumper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* pixieset.com full size image scraper | |
| * | |
| * Rips all images in highest quality | |
| * | |
| * To use scroll to the very bottom of the album and press F12 then paste the below snippet in and press enter. | |
| * The full file list will be copied to your clipboard afterwards. You can use jdownloader to easily download the full list. | |
| */ | |
| (() => { | |
| const data = document.querySelectorAll('.masonry-brick img') | |
| let arr = [] | |
| for (let i = 0; i < data.length; i++) { | |
| arr.push(data[i].src.replace(/-medium/g, '-xxlarge')) | |
| } | |
| console.log(arr) | |
| let dataToArray = arr.toString().split(',').map(item => item.trim()) | |
| const dummy = document.createElement('textarea') | |
| document.body.appendChild(dummy) | |
| dummy.value = dataToArray.join('\n') | |
| dummy.select() | |
| document.execCommand('copy') | |
| document.body.removeChild(dummy) | |
| })() |
Thank you!
For Firefox, and with xxlarge (~ 1600x2400) it's simpler:
- Scroll to bottom of Pixieset page to see all photos loaded.
- open Console (F12)
- Paste:
(() => {
const data = document.querySelectorAll('img');
let arr = [];
data.forEach(img => {
let url = img.src || img.getAttribute('data-src');
if (url && url.includes('images.pixieset.com')) {
arr.push(url.replace(/-medium|-large|-xlarge/g, '-xxlarge'));
}
});
if (arr.length > 0) {
console.log(arr.join('\n'));
} else {
console.warn('No matching images found.');
}
})();
- the URLs should be printed out now. Right click on that list and 'Copy Object'.
- Paste into a new text file and save it as
url_list_pasted.txt - Follow @DeflateAwning's
wget -i "url_list_pasted.txt" -P "output_folder/". - All the images should download serially (couldn't figure out parallelism) in the folder
đź§ How to use
-
Create a file
urls.jsonand put your image URLs inside:["https://example.com/image1.jpg", "https://example.com/image2.png"]
-
Install dependencies
npm init -y && npm i axios archiver cli-progress mime-types -
Run the script
node yourfile.js urls.json
đź’ľ The images will be downloaded with progress tracking, and a images.zip file will be created inside the output folder.
const fs = require("fs");
const fsp = fs.promises;
const path = require("path");
const axios = require("axios");
const Archiver = require("archiver");
const mime = require("mime-types");
const cliProgress = require("cli-progress");
const OUTPUT_DIR = path.resolve(__dirname, "output");
const DOWNLOAD_DIR = path.join(OUTPUT_DIR, "downloads");
const ZIP_PATH = path.join(OUTPUT_DIR, "images.zip");
const FALLBACK_URLS = [
"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Fronalpstock_2.jpg/640px-Fronalpstock_2.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Phoenicopterus_ruber_in_S%C3%A3o_Paulo_Zoo.jpg/640px-Phoenicopterus_ruber_in_S%C3%A3o_Paulo_Zoo.jpg"
];
async function readUrlsFromArg() {
const arg = process.argv[2];
if (!arg) return FALLBACK_URLS;
const p = path.resolve(process.cwd(), arg);
const raw = await fsp.readFile(p, "utf8");
const arr = JSON.parse(raw);
if (!Array.isArray(arr)) throw new Error("Le fichier JSON doit contenir un tableau d'URLs.");
return arr;
}
function buildFileName(url, index, contentType) {
const u = new URL(url);
let base = path.basename(u.pathname);
if (!base || base === "/") base = `image_${index + 1}`;
const hasExt = path.extname(base);
if (!hasExt) {
const ext = mime.extension(contentType || "") || "bin";
base = `${base}.${ext}`;
}
base = base.replace(/[^a-zA-Z0-9._-]/g, "_");
return base;
}
async function ensureUnique(destDir, fileName) {
let name = fileName;
let counter = 1;
while (true) {
const full = path.join(destDir, name);
try {
await fsp.access(full);
const parsed = path.parse(fileName);
name = `${parsed.name}(${counter++})${parsed.ext}`;
} catch {
return path.join(destDir, name);
}
}
}
async function downloadWithProgress(url, destPath, bars) {
const response = await axios.get(url, { responseType: "stream", validateStatus: s => s >= 200 && s < 400 });
const total = Number(response.headers["content-length"]) || 0;
const type = response.headers["content-type"];
// Si le nom a été généré sans extension correcte (cas rare), on pourrait l'ajuster ici
const outStream = fs.createWriteStream(destPath);
return new Promise((resolve, reject) => {
let downloaded = 0;
if (total > 0) bars.file.start(total, 0);
response.data.on("data", (chunk) => {
downloaded += chunk.length;
if (total > 0) bars.file.update(downloaded);
bars.total.increment(chunk.length);
});
response.data.on("error", reject);
outStream.on("finish", () => {
if (total > 0) bars.file.update(total);
resolve({ bytes: downloaded, contentType: type });
});
response.data.pipe(outStream);
});
}
async function makeZip(fromDir, toZipPath) {
await fsp.mkdir(path.dirname(toZipPath), { recursive: true });
await new Promise((resolve, reject) => {
const output = fs.createWriteStream(toZipPath);
const archive = Archiver("zip", { zlib: { level: 9 } });
output.on("close", resolve);
archive.on("error", reject);
archive.pipe(output);
archive.directory(fromDir, false);
archive.finalize();
});
}
async function main() {
const urls = await readUrlsFromArg();
if (urls.length === 0) throw new Error("Aucune URL fournie.");
await fsp.mkdir(DOWNLOAD_DIR, { recursive: true });
const multibar = new cliProgress.MultiBar({
clearOnComplete: false,
hideCursor: true,
format: "{name} {bar} {percentage}% | {value}/{total}"
}, cliProgress.Presets.shades_classic);
const totalBar = multibar.create(1, 0, { name: "Total" });
// On initialisera la taille totale si possible, autrement on la laissera croître.
// Première passe: tenter de sommer les Content-Length
let sumLengths = 0;
const headResults = await Promise.allSettled(urls.map(u => axios.head(u).catch(() => null)));
headResults.forEach(r => {
if (r.status === "fulfilled" && r.value) {
const len = Number(r.value.headers["content-length"]) || 0;
if (len > 0) sumLengths += len;
}
});
if (sumLengths > 0) totalBar.setTotal(sumLengths);
const results = [];
for (let i = 0; i < urls.length; i++) {
const url = urls[i];
let contentType;
try {
const h = await axios.head(url);
contentType = h.headers["content-type"];
} catch {}
const baseName = buildFileName(url, i, contentType);
const destPath = await ensureUnique(DOWNLOAD_DIR, baseName);
const fileBar = multibar.create(1, 0, { name: path.basename(destPath) });
try {
const { bytes } = await downloadWithProgress(url, destPath, { file: fileBar, total: totalBar });
results.push({ url, path: destPath, bytes, ok: true });
} catch (err) {
fileBar.stop();
results.push({ url, path: destPath, bytes: 0, ok: false, error: String(err.message || err) });
console.error(`\nErreur sur ${url}:`, err.message || err);
} finally {
fileBar.stop();
}
}
multibar.stop();
// Création du ZIP
console.log("\nCréation du ZIP...");
await makeZip(DOWNLOAD_DIR, ZIP_PATH);
console.log(`ZIP créé: ${ZIP_PATH}`);
// Petit récap
const ok = results.filter(r => r.ok).length;
const ko = results.length - ok;
console.log(`\nTéléchargements réussis: ${ok}/${results.length}`);
if (ko) {
console.log("Échecs:");
results.filter(r => !r.ok).forEach(r => console.log(" - ", r.url));
}
}
main().catch(err => {
console.error("\nÉchec:", err);
process.exit(1);
});
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My fork does that automatically: https://gist.github.com/DeflateAwning/8567037cc7125cb3ede76fed40d27ba1