Skip to content

Instantly share code, notes, and snippets.

@19h
Last active September 4, 2022 02:59
Show Gist options
  • Save 19h/2824e50d9a3bac75b6f49fc7b9d88dd7 to your computer and use it in GitHub Desktop.
Save 19h/2824e50d9a3bac75b6f49fc7b9d88dd7 to your computer and use it in GitHub Desktop.
Instagram following followers network graph dumper crawler spider node.js api / private api
const { IgApiClient, IgLoginTwoFactorRequiredError } = require('instagram-private-api');
const inquirer = require('inquirer');
const Bluebird = require('bluebird');
const fs = require('fs');
process.env.IG_USERNAME = 'xxx';
process.env.IG_PASSWORD = 'xxx';
const ig = new IgApiClient();
ig.state.generateDevice(process.env.IG_USERNAME);
ig.state.deserialize(
fs
.readFileSync('./state.json')
.toString(),
);
const waitInSeconds = (seconds) => {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, seconds * 1000);
});
};
async function getFollowers(
username,
ig,
opts = {},
) {
const { delay, limit } = opts;
const id = await ig.user.getIdByUsername(username);
const followersFeed = await ig.feed.accountFollowing(id);
let followers = [];
let reqId = 0;
do {
reqId += 1;
console.log(`Requesting followers (iter: ${reqId}) for ${username}...`);
const items = await followersFeed.items();
followers = [...followers, ...items];
if (limit && limit !== -1) {
if (followers.length >= limit) {
break;
}
}
await waitInSeconds(delay);
} while (followersFeed.isMoreAvailable());
return followers;
}
(async () => {
/*await ig.simulate.preLoginFlow();
const loggedInUser =
await Bluebird.try(() => ig.account.login(process.env.IG_USERNAME, process.env.IG_PASSWORD)).catch(
IgLoginTwoFactorRequiredError,
async err => {
const { username, totp_two_factor_on, two_factor_identifier } = err.response.body.two_factor_info;
// decide which method to use
const verificationMethod = totp_two_factor_on ? '0' : '1'; // default to 1 for SMS
// At this point a code should have been sent
// Get the code
const { code } = await inquirer.prompt([
{
type: 'input',
name: 'code',
message: `Enter code received via ${verificationMethod === '1' ? 'SMS' : 'TOTP'}`,
},
]);
// Use the code to finish the login process
return ig.account.twoFactorLogin({
username,
verificationCode: code,
twoFactorIdentifier: two_factor_identifier,
verificationMethod, // '1' = SMS (default), '0' = TOTP (google auth for example)
trustThisDevice: '1', // Can be omitted as '1' is used by default
});
});
process.nextTick(async () => await ig.simulate.postLoginFlow().catch(() => {}));*/
ig.state.serialize().then(data => require('fs').writeFileSync('./state.json', JSON.stringify(data)));
const me_id = await ig.user.getIdByUsername('in19h');
const me_following = await getFollowers('in19h', ig);
console.log("Found %s following", me_following.length);
const other_names =
me_following.map(f => f.username);
const others = new Map();
const others_id = new Map();
for (const [i, other_name] of other_names.entries()) {
console.log(`Processing ${other_name} (${i} of ${other_names.length})...`);
try {
const user_rel =
JSON.parse(
fs.readFileSync(`./following/${other_name}.json`)
.toString(),
);
others_id.set(user_rel.id, other_name);
others.set(user_rel.id, user_rel.followers);
} catch {
const followers =
await getFollowers(
other_name,
ig,
{
delay: 0,
limit: 50,
},
);
const other_id = await ig.user.getIdByUsername(other_name);
others_id.set(other_id, other_name);
others.set(other_id, followers);
fs.writeFileSync(
`./following/${other_name}.json`,
JSON.stringify(
{
id: other_id,
followers
},
undefined,
4,
),
);
}
}
const reciprocals = new Map();
for (const [other_id, following] of Array.from(others)) {
for (const user of following) {
const reciprocal = reciprocals.get(user.pk) || [];
reciprocal.push(`"${others_id.get(other_id)} (${other_id})" -> "${user.username} (${user.pk})"`)
reciprocals.set(user.pk, reciprocal);
}
}
const out = new Set();
for (const user of me_following) {
if (reciprocals.has(user.pk)) {
console.log(`Found reciprocal for ${user.username} (${user.pk}), followed by ${reciprocals.get(user.pk).length} users..`);
out.add(`"in19h (${me_id})" -> "${user.username} (${user.pk})";`);
for (const reciprocal of reciprocals.get(user.pk)) {
out.add(reciprocal);
}
}
}
const dot = `digraph G {
rankdir = LR;
${Array.from(out).join('\n')}
}`;
fs.writeFileSync('graph.dot', dot);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment