NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Instagram post comment usernames collector // @include https://www.instagram.com/p/* // @grant GM.setClipboard // @license MIT // @version 0.0.5 // ==/UserScript== class Tool { constructor() { this._wait = 0; this._dataString = ""; console.log('Create comments tool') } download(filename, text) { let pom = document.createElement('a'); pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); pom.setAttribute('download', filename); if (document.createEvent) { let event = document.createEvent('MouseEvents'); event.initEvent('click', true, true); pom.dispatchEvent(event); } else { pom.click(); } } setWait(timeout) { this._wait = timeout; } getCommentSection() { let popup = this.getSectionByXpath(document, '/html/body/span/section/main/div/div/article/div[2]/div[1]/ul'); if (popup) { return popup } let post = this.getSectionByXpath(document, '/html/body/div[2]/div/div[2]/div/article/div[2]/div[1]/ul'); if (post) { return post } } getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } isCommentSection() { return !!this.getCommentSection(); } isWait() { if (this._wait > 0) { this._wait--; return true } return false } getCommentButton() { let comments = this.getCommentSection(); let loadMoreButton; for (let liItem of comments.children) { let liChild = liItem.children[0]; if (!liChild) { return } if (liChild.nodeName === 'BUTTON') { loadMoreButton = liChild; break } } return loadMoreButton; } isCommentButton() { return !!this.getCommentButton(); } isHasData() { return !!this._dataString; } pressMoreComments() { let button = this.getCommentButton(); if (!button) { return } console.log('Load more comments'); button.click(); } getSectionByXpath(root, path) { return document.evaluate(path, root, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; } getCommentUsername(root) { let element = this.getSectionByXpath(root, 'div/div/div/h3/a'); if (!element) { element = this.getSectionByXpath(root, 'div/div/div/h2/a'); } if (element) { return element.href } return "" } getCommentData(root) { let element = this.getSectionByXpath(root, 'div/div/div/span'); if (element) { return element.textContent } return "" } copyData() { console.log('Process data copy'); let withCommentsString = ""; let usernamesString = ""; let count = 0; let comments = this.getCommentSection(); let children = comments.children; console.log('Posts count: ' + children.length); let dataArray = []; for (let item of children) { let username = this.getCommentUsername(item); if (!username) { continue } let comment = this.getCommentData(item); dataArray.push([username, comment]); count++; } dataArray.shift(); count -= 1; console.log('Urls count: ' + count); let maxLength = 0; dataArray.forEach((array) => { if (array[0].length > maxLength) { maxLength = array[0].length; } }); maxLength += 1; dataArray.forEach(array => { array[0] += ' '.repeat(maxLength - array[0].length) }); dataArray.forEach(array => { withCommentsString += array[0] + array[1] + '\n'; usernamesString += array[0] + '\n' }); withCommentsString = withCommentsString.replace(/\n$/, ""); usernamesString = usernamesString.replace(/\n$/, ""); // console.log('Trying copy to clipboard...'); // GM.setClipboard(withCommentsString); this.download("comments.txt", withCommentsString); setTimeout(() => this.download("usernames.txt", usernamesString), 100); // alert('Collecting data finished'); this._dataString = dataString } isPathChanged() { if (this._lastPath !== location.pathname) { this._lastPath = location.pathname; return true } } isPathValid() { return /^\/p\//.test(location.pathname); } clearData() { this._dataString = ""; } update() { if (!this.isPathValid()) { return } if (this.isPathChanged()) { console.log('Url is changed, clear data and collect again...'); this.clearData() } if (this.isHasData()) { return } if (this.isWait()) { return } if (!this.isCommentSection()) { this.setWait(60); return } // Assuming if no comments button - comments are fully loaded // TODO: check if (this.isCommentButton()) { this.pressMoreComments(); this.setWait(this.getRandom(60, 80)); } else { this.copyData(); } } } let tool = new Tool(); function loop() { tool.update(); window.requestAnimationFrame(loop) } window.requestAnimationFrame(loop);