Skip to content

Instantly share code, notes, and snippets.

@torohima
Forked from thinhbuzz/download.js
Created July 19, 2021 17:06
Show Gist options
  • Save torohima/4978c845158db6eb6337e76f28f16378 to your computer and use it in GitHub Desktop.
Save torohima/4978c845158db6eb6337e76f28f16378 to your computer and use it in GitHub Desktop.
Download all photos from facebook Page
(async () => {
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function findToken() {
const tags = Array.from(
document.body.querySelectorAll("script:not([src])")
);
let fb_dtsg = "";
let id = "";
for (const tag of tags) {
let matches = tag.textContent.match(
/"token":"([a-zA-Z0-9_-]+):([0-9]+):([0-9]+)"/
);
if (matches) {
fb_dtsg = `${matches[1]}:${matches[2]}:${matches[3]}`;
matches = tag.textContent.match(/"pageID":"([0-9]+)"/);
if (matches) {
id = matches[1];
break;
} else {
matches = tag.textContent.match(
/"rawSectionToken":"([0-9]+):([0-9]+)"/
);
if (matches) {
id = btoa(`app_collection:${matches[1]}:${matches[2]}:5`);
break;
}
}
}
}
return { fb_dtsg, id };
}
async function findDocId(method) {
const regex = new RegExp(
`__d\\("${method}\\.graphql"(.*)params:\\{id:"([0-9]+)"`
);
const promises = await Promise.all(
Array.from(
document.head.querySelectorAll(
'script[crossorigin="anonymous"][async="1"][src]'
)
).map((tag) => {
return fetch(tag.getAttribute("src"))
.then((response) => response.text())
.then((content) => {
return content.match(regex);
});
})
);
return promises.find((item) => !!item)[2];
}
async function getLinks(
{ fb_dtsg, id, doc_id, isPage, method },
cursor = null
) {
const variables = isPage
? `{"count":10,"cursor":${cursor},"scale":4,"id":"${id}"}`
: `{"count":8,"cursor":${cursor},"scale":1,"id":"${id}"}`;
const data = {
doc_id, // __d\("PagesCometPhotosTabMainViewAllPhotosSectionPaginationQuery\.graphql"(.*)params:\{id:"([0-9]+)"
fb_dtsg, // "token":"([a-zA-Z0-9]+):([0-9]+):([0-9]+)"
variables,
fb_api_caller_class: "RelayModern",
fb_api_req_friendly_name: method,
};
const formBody = [];
for (const property in data) {
const encodedKey = encodeURIComponent(property);
const encodedValue = encodeURIComponent(data[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
return fetch("https://www.facebook.com/api/graphql/", {
headers: {
"content-type": "application/x-www-form-urlencoded",
"user-agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
"x-fb-friendly-name": method,
},
body: formBody.join("&"),
method: "POST",
})
.then((response) => response.json())
.then(({ data }) => {
if (isPage) {
return {
images: data.node.allPhotos.edges.map((item) => {
return {
...item.node.image,
...item.node.viewer_image,
};
}),
page: data.node.allPhotos.page_info,
};
}
return {
images: data.node.pageItems.edges.map(
(item) => item.node.node.viewer_image
),
page: data.node.pageItems.page_info,
};
});
}
window.scrollTo(0, document.body.scrollHeight);
await sleep(1000);
let cursor = null;
const limit = +prompt("Số link tối đa sẽ lấy", "999999") || 999999;
window.allImages = [];
const { fb_dtsg, id } = findToken();
const isPage = !!id.match(/^([0-9]+)$/);
const method = isPage
? "PagesCometPhotosTabMainViewAllPhotosSectionPaginationQuery"
: "ProfileCometAppCollectionPhotosRendererPaginationQuery";
const doc_id = await findDocId(method);
if (!fb_dtsg || !doc_id) {
throw new Error("Không tìm thấy token");
}
console.log("%cBắt đầu lấy link", "color: green;");
while (true) {
let { images, page } = await getLinks(
{ fb_dtsg, id, doc_id, isPage, method },
cursor ? `"${cursor}"` : null
);
window.allImages.push(...images);
console.log("%cĐã lấy được %d link ảnh", "color: green;", window.allImages.length);
// await sleep(1000); // sleep 1s
if (!page.has_next_page) {
break;
}
cursor = page.end_cursor;
if (++window.allImages.length > limit) {
break;
}
}
console.log(window.allImages);
const styles = ["color: green", "font-size: 20px", "padding: 10px"].join(";");
console.log(
"%cĐã lấy thành công %d link ảnh, gõ copy(window.allImages.map(({ uri }) => uri).join('\\n')) để sao chép links vào clipboard",
styles,
window.allImages.length
);
})().catch((error) => {
console.log(error);
alert("Vui lòng tải lại trang và thử lại.");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment