使用JS控制台删除推文



我正在尝试删除Twitter页面上JS控制台中的推文。如果我手动选择按钮然后点击,我可以手动运行3种不同的功能。

const delButton=()=>{
document.querySelectorAll('[data-testid="caret"]')[0].click()
};
const clickDel=()=>{
document.querySelector("#layers > div.css-1dbjc4n.r-1d2f490.r-105ug2t.r-u8s1d.r-zchlnj.r-ipm5af > div > div > div > div:nth-child(2) > div.css-1dbjc4n.r-yfoy6g.r-z2wwpe.r-xnswec.r-1ekmkwe.r-1udh08x.r-u8s1d > div > div > div > div:nth-child(1) > div.css-1dbjc4n.r-16y2uox.r-1wbh5a2 > div > span");
};
const confirmDel=()=>{
document.querySelector("#layers > div:nth-child(2) > div > div > div > div > div > div.css-1dbjc4n.r-1awozwy.r-1kihuf0.r-18u37iz.r-1pi2tsx.r-1777fci.r-1pjcn9w.r-fxte16.r-1xcajam.r-ipm5af.r-9dcw1g > div.css-1dbjc4n.r-1awozwy.r-yfoy6g.r-1867qdf.r-1jgb5lz.r-pm9dpa.r-1ye8kvj.r-1rnoaur.r-d9fdf6.r-1sxzll1.r-13qz1uu > div.css-1dbjc4n.r-18u37iz.r-13qz1uu > div.css-18t94o4.css-1dbjc4n.r-1dgebii.r-42olwf.r-sdzlij.r-1phboty.r-rs99b7.r-16y2uox.r-1w2pmg.r-1vuscfd.r-1dhvaqw.r-1ny4l3l.r-1fneopy.r-o7ynqc.r-6416eg.r-lrvibr > div > span > span").click()
} 
delButton();
clickDel();
confirmDel();

我尝试了几种不同的方法,如果我通过在控制台中运行每个函数来手动运行它们,它就会起作用。然而,当我试图将它们放入一个运行所有3个的函数中时,第二个函数没有点击,因为它还没有准备好。在启动它们之前,我尝试过使用setTimeout,但它仍然不起作用。我也尝试过使用异步和等待,但我认为我对这个问题的理解是有限的。

const runEmAll=()=>{
setTimeout(delButton(), 1000); 
setTimeout(clickDel(), 1000);
setTimeout(confirmDel(), 1000);
}
runEmAll();
// or I also tried...
const runDel = async ()=>{
await delButton();
}
runDel().then(clickDel());

再说一遍,那没用。。我得到的错误是

VM1649:2 Uncaught TypeError: Cannot read property 'click' of null

参考点击删除功能

。打开Chrome或其他浏览器。

(如果浏览器没有铬(。

打开twitter。

点击个人资料或点击推文并回复

按F12(显影剂选项(

单击控制台选项卡

粘贴这些代码(twitter语言必须是英语(

var delTweets = function () {
var tweetsRemaining = 
document.querySelectorAll('[role="heading"]+div')[1].textContent;
console.log('Remaining: ', tweetsRemaining);
window.scrollBy(0, 10000);
document.querySelectorAll('[aria-label="More"]').forEach(function 
(v, i, a) {
v.click();
document.querySelectorAll('span').forEach(function (v2, i2, a2) {
if (v2.textContent === 'Delete') {
v2.click();
document.querySelectorAll('[data-testid="confirmationSheetConfirm"]').forEach(function (v3, i3, a3) {
v3.click();
});
}
else {
document.body.click();
}
});
});
setTimeout(delTweets, 4000); //less than 4000 might be rate limited or account suspended. increase timeout if any suspend or rate limit happens
}
delTweets();

添加到Mazen Alhrazi答案(谢谢!(,于2022年12月21日测试,这是有效的:

(async () => {
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

let found;

while (found = document.querySelectorAll('[data-testid="caret"]').length) {

// get first tweet
let tweet = document.querySelectorAll('[data-testid="tweet"]')[0];

// if it is a retweet, undo it
if (tweet.querySelectorAll('[data-testid="unretweet"]').length) {
tweet.querySelectorAll('[data-testid="unretweet"]')[0].click()
await sleep(1000)
document.querySelectorAll('[data-testid="unretweetConfirm"]')[0].click()
await sleep(1000)      
}
// is a tweet
else {
if (new Date(document.querySelectorAll('[datetime]')[0].getAttribute('datetime')) < new Date('2018')) {
console.log('Limit date reach')
break;
}

tweet.querySelectorAll('[data-testid="caret"]')[0].click()
await sleep(1000)
document.querySelectorAll('[role="menuitem"]')[0].click()
await sleep(1000)
document.querySelectorAll('[data-testid="confirmationSheetConfirm"]')[0].click()
}
}

if (!found)
console.log('No more tweets found');

})();

我的主要问题是转发在你自己的推文中间,所以你必须同时删除:根据类型的不同,取消推文和删除。

我添加了一个过滤器,这样你就不会删除Date(示例中为2018(之前的推文。如果不需要,请编辑或删除该if

它并不完美,有些对话/回复有一些问题,但它对我有效。也许其他人会解决这种情况:(

我使用了Uzay的解决方案,但它停止了工作。这是我的解决方案,它还可以删除转发。

要使用它,请转到您的Twitter时间线,然后转到";tweets";选项卡删除所有推文,或者转到";回复";选项卡删除回复。

将以下代码粘贴到浏览器JavaScript控制台中。

在粘贴之前,请确保在代码中设置了twitter句柄!

脚本1:-删除所有推文

// TO DELETE TWEETS MUST BE RUN FROM https://twitter.com/{yourTwitterHandle}
// TO DELETE REPLIES MUST BE RUN FROM https://twitter.com/{yourTwitterHandle}/with_replies
// IMPORTANT IMPORTANT IMPORTANT - SET YOUR TWITTER HANDLE IN THE NEXT LINE!
// IMPORTANT IMPORTANT IMPORTANT - SET YOUR TWITTER HANDLE IN THE NEXT LINE!
const yourTwitterHandle = "@yourhandle";
// one every 10 seconds to avoid Twitter noticing
const waitTimeSeconds = 10
const sleep = async (seconds) => new Promise(resolve => setTimeout(resolve, seconds * 1000));
const main = async () => {
while (true) {
await walkTweets();
await sleep(waitTimeSeconds)
}
}
const walkTweets = async () => {
let articles = document.getElementsByTagName('article');
for (article of articles) {
const spanElements = article.querySelectorAll('span');
for (spanElement of spanElements) {
// delete if it is a retweet
if (spanElement.textContent === "You reposted") {
article.scrollIntoView();
try {
const retweetElement = article.querySelector('[data-testid="unretweet"]');
if (retweetElement) {
retweetElement.click();
document.querySelector('[data-testid="unretweetConfirm"]').click();
}
} catch (e) {}
return
}
if (spanElement.textContent === yourTwitterHandle) {
// in this case it might be a tweet or a reply
article.scrollIntoView();
try {
// try to delete a reply
const tweetReplyElement = article.querySelectorAll('[aria-label="More"]')[1];
if (tweetReplyElement) {
tweetReplyElement.click()
Array.from(document.getElementsByTagName('*')).find(el => el.textContent.trim() === 'Delete').click()
document.querySelector('[data-testid="confirmationSheetConfirm"]').click();
return
}
} catch (e) {}
try {
// try to delete a tweet
const tweetElement = article.querySelector('[aria-label="More"]');
if (tweetElement) {
article.scrollIntoView();
tweetElement.click()
Array.from(document.getElementsByTagName('*')).find(el => el.textContent.trim() === 'Delete').click()
document.querySelector('[data-testid="confirmationSheetConfirm"]').click();
return
}
} catch (e) {}
}
}
}
}
main()

脚本2:-删除所有点赞

// MUST BE RUN FROM https://twitter.com/{yourTwitterHandle}/likes
// one every 10 seconds to avoid Twitter noticing
const waitTimeSeconds = 2;
const maxRetries = 3;
const sleep = async (seconds) => new Promise(resolve => setTimeout(resolve, seconds * 1000));
const unlikeAllTweets = async () => {
let counter = 0;
let retryCount = 0;
while (true) {
try {
await sleep(waitTimeSeconds);
const element = document.querySelector('[data-testid="unlike"]');
if (element === null) {
if (retryCount >= maxRetries) {
console.log('element was null, no more likes found after retries, finished');
return;
}
console.log(`element was null, retrying... (${retryCount + 1}/${maxRetries})`);
retryCount++;
continue;
}
element.scrollIntoView();
element.click();
counter++;
retryCount = 0;  
console.log(`Unliked a tweet. Total so far: ${counter}`);
await sleep(0.5);
// Remove the element's parent from the DOM to avoid it clagging up
if (element.parentElement) {
element.parentElement.remove();
}
} catch (error) {
console.error('An error occurred:', error);
}
}
};
unlikeAllTweets();

根据Phix的建议,我成功了,

()=>{
setTimeout(delButton, 1000); 
setTimeout(clickDel, 1000);
setTimeout(confirmDel, 1000);
}

login>在您的个人资料上>推文选项卡>执行

function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
document.querySelectorAll('[data-testid="caret"]')[0].click()
await sleep(1000)
document.querySelectorAll('[role="menuitem"]')[0].click()
await sleep(1000)
document.querySelectorAll('[data-testid="confirmationSheetConfirm"]')[0].click()

var delRetweets = function () {
var tweetsRemaining = document.querySelectorAll('[role="heading"]+div')[1]
.textContent;
window.scrollBy(0, 10000);
document
.querySelectorAll('[style="color: rgb(0, 186, 124);"]')
.forEach(function (v) {
v.click();
document.querySelectorAll("span").forEach(function (v2, i2, a2) {
if (v2.textContent === "Undo repost") {
v2.click();
} else {
document.body.click();
}
});
});
setTimeout(delRetweets, 4000); //less than 4000 might be rate limited or account suspended. increase timeout if any suspend or rate limit happens
};
delRetweets();
var likeTweets = function () {
var tweets = document.querySelectorAll('[style="color: rgb(249, 24, 128);"]');
var index = 0;
var clickCount = 0;
var clickNextTweet = function () {
if (index < tweets.length && clickCount < 999) {
tweets[index].click();
index++;
clickCount++;
if (clickCount % 50 === 0) {
// Check if 50 clicks limit reached, wait for 15 minutes before continuing
setTimeout(clickNextTweet, 900000); // Timeout for 15 minutes (900000 milliseconds)
} else {
setTimeout(clickNextTweet, 9000); // Timeout between each click action (adjust as needed)
}
} else {
window.scrollBy(0, 10000);
if (clickCount >= 999) {
console.log("Maximum click limit reached. Stopping the process.");
} else {
setTimeout(likeTweets, 9000); // Timeout before scrolling and starting the process again (adjust as needed)
}
}
};
clickNextTweet();
};
likeTweets();

根据Adam Boyle的回答,如果你想一次只删除50条转发:

var counter = 0;
var delRetweets = function () {
if (counter >= 50) {
return;
}

window.scrollBy(0, 10000);
document
.querySelectorAll('[style="color: rgb(0, 186, 124);"]')
.forEach(function (v) {
if (counter >= 50) {
return;
}
v.click();
document.querySelectorAll("span").forEach(function (v2) {
if (v2.textContent === "Undo Retweet") {
v2.click();
counter++;
console.log(`Retweet delete triggered. Total retweets deleted: ${counter}`); // log the count here
} else {
document.body.click();
}
});
});
setTimeout(delRetweets, 4000);
};
delRetweets();

最新更新