簡體   English   中英

通過控制台在 Facebook 頁面上發表評論

[英]Post comments on Facebook page via console

與圖片中一樣,Facebook 評論框沒有提交按鈕,當您寫一些內容並按 Enter 按鈕時,評論就會發布。

我想通過在控制台中運行的 JavaScript 提交評論,但我試圖觸發 Enter 事件,提交 DOM 事件。 無法讓它工作。

臉書評論框

當前的評論框不是<form>內的傳統<textarea> <form> 他們在 div 上使用 contenteditable 屬性。 為了在這種情況下提交,您需要監聽鍵盤事件之一( keydownkeypresskeyup )並查找鍵代碼 13 的Enter鍵。

在這種情況下,看起來 FB 正在偵聽keydown evt,因此當我運行此代碼時,我能夠偽造提交評論:

function fireEvent(type, element) {
    var evt;

    if(document.createEvent) {
        evt = document.createEvent("HTMLEvents");
        evt.initEvent(type, true, true);
    } else {
        evt = document.createEventObject();
        evt.eventType = type;
    }

    evt.eventName = type;
    evt.keyCode = 13;
    evt.which = 13;

    if(document.createEvent) {
        element.dispatchEvent(evt);
    } else {
        element.fireEvent("on" + evt.eventType, evt);
    }
}

fireEvent('keydown', document.querySelector('[role="combobox"]._54-z span span'));

有幾點需要注意。 ._54-z類是他們碰巧在我的頁面上使用的類。 你的旅費可能會改變。 使用開發工具確保您獲取正確的元素(它應該具有 aria 角色“組合框”)。 此外,如果您希望支持舊瀏覽器,則必須調整上面的fireEvent函數代碼。 我只在最新的 Chrome 中測試了上面的例子。

最后,為了使您的問題復雜化,Facebook 正在使用 React 創建當前頁面的虛擬 DOM 表示。 如果您在組合框中手動輸入字符,然后運行上面的代碼,它將按預期工作。 但是您將無法將組合框最里面的<span>的 innerHTML 設置為您要執行的操作,然后觸發keydown 您可能需要觸發組合框上的change事件,以確保您的消息持久保存到虛擬 DOM。

這應該讓你開始! 希望有幫助!

幾年后,這篇文章仍然具有相關性,實際上是我發現的唯一一篇關於此的文章,而我正在嘗試通過 JS 代碼(類似於原始問題的任務)發布到 FB 組。

終於我破解了它 - 測試和工作:

  setTimeout(() => {
        document.querySelector('[placeholder^="Write something"]').click();
        setTimeout(() => {
            let postText = "I'm a Facebook post from Javascript!";
            let dataDiv = document.querySelector('[contenteditable] [data-offset-key]');
            let dataKey = dataDiv.attributes["data-offset-key"].value;
            //Better to construct the span structure exactly in the form FB does it
            let spanHTML = `<span data-offset-key="${dataKey}"><span data-text="true">${postText}</span></span>`;
            dataDiv.innerHTML = spanHTML;

            let eventType = "input";
            //This can probably be optimized, no need to fire events for so many elements
            let div = document.querySelectorAll('div[role=presentation]')[1].parentElement.parentElement;
            let collection = div.getElementsByTagName("*");
            [...collection].forEach(elem => {
                let evt = document.createEvent("HTMLEvents");
                evt.initEvent(eventType, true, true); //second "true" is for bubbling - might be important
                elem.dispatchEvent(evt);
            });
            //Clicking the post button
            setTimeout(()=>{
                document.querySelector('.rfloat button[type=submit][value="1"]').click();
            },2000);
        }, 4000);
    }, 7000);

所以這就是故事,正如我從這篇文章中以前的評論和深入研究 FB 代碼中了解到的那樣。 FB 使用 React,因此對 DOM 的更改不會“流行”,因為 React 使用虛擬 DOM。 如果您在從 JS 更改 DOM 后單擊“發布”,則不會發布文本。 這就是為什么您必須按照此處的建議手動觸發事件。

然而 - 為正確的元素觸發正確的事件是一件棘手的事情,幾乎讓我無法成功。 幾個小時后,我發現這段代碼有效,可能是因為它針對多個元素,從組帖子的父元素開始,深入到所有子元素並為每個子元素觸發事件(這是[...collection].forEach(elem => { bit). 正如所寫的那樣,顯然可以優化以找到需要觸發事件的一個正確元素。

至於觸發哪個事件,正如這里所討論的,我已經嘗試了幾個,發現"input"就是一個。 此外,代碼在我將initEvent的第二個參數initEventtrue后開始工作 - 即evt.initEvent(eventType, true, true) 不確定這是否有所作為,但我已經有足夠的時間擺弄這個,如果它有效,那對我來說就足夠了。 順便說一句,當然可以使用setTimeout

(未成功)深入 FB 的 React 數據結構

關於我嘗試走的另一條路徑的另一個注意事項,但最終沒有結果:使用 React Dev Tools Chrome 擴展程序,您可以使用$r訪問組件本身及其所有propsstate 令人驚訝的是,這也可以控制台之外運行,因此使用 TamperMonkey 之類的東西來運行 JS 代碼也可以。 我實際上找到了 FB 將帖子文本保持在狀態的位置。 作為參考,它位於一個名為ComposerStatusAttachmentMentionsInputContainer的組件中,該組件負責帖子的編輯器部分,下面是訪問它的代碼。

$r實際上提供了對很多 React 東西的訪問,比如setState 從理論上講,我相信我可以使用它來設置 React 中帖子文本的狀態(如果您了解 React,您會同意setState將是觸發將保持不變的更改的正確方法)。

然而,經過很長一段時間后,我發現這很難做到,因為 FBReact之上使用了一個名為 Draft.js 的框架,它處理所有帖子。 這個框架有自己的方法、類、數據結構等等,如果沒有源代碼,很難從“外部”操作這些。

我還嘗試手動觸發附加到組件的onchange函數,這不起作用,因為我沒有正確的參數,這些參數是諸如來自 Draft.Js 的editorContentselectionContent的對象,需要使用我無權訪問諸如 Draft.js 中的Modifier方法(你到底是如何從外部訪問源代碼中糾纏在一起的庫中的靜態方法的?我沒能做到)。

無論如何,訪問存儲文本的狀態變量的代碼,只要你有 React 開發工具並且你已經突出顯示ComposerStatusAttachmentMentionsInputContainer

let blockMap = $r["state"].activeEditorState["$1"].currentContent.blockMap;
let innerObj = JSON.parse(JSON.stringify(blockMap)); //this is needed to get the next property as it's not static or something

let id = Object.keys(innerObj)[0]; //get the id from the obj property 
console.log(innerObj[id].text); //this is it!

但正如我寫的,這幾乎沒用:-)

由於我無法通過“正常”的 facebook 頁面發表評論,我記得他們也有移動版本,在 m.facebook 上。 com,那里,他們仍然有提交按鈕,所以根據您的需要,這可能是一個不錯的選擇

所以,你可以去移動 facebook 帖子(例如https://m.facebook.com/${author}/posts/${postId} )然后做

// Find the input element that saves the message to be posted
document.querySelector("input[name='comment_text']").value='MESSAGE TO POST';
// find the submit button, enable it and click it
const submitButton = document.querySelector("button[name='submit']");
submitButton.disabled = false;
submitButton.click();

這是經過 3 周試驗后的可行解決方案(使用 @Benjamin Solum 的fireEvent函數):

  • 此版本僅針對頁面上的第一篇文章發表評論(通過使用querySelector方法)
  • 此版本只能在您的個人牆上使用(除非您更改查詢選擇器)

     function fireEvent(type, element, keyCode) { var evt; if(document.createEvent) { evt = document.createEvent("HTMLEvents"); evt.initEvent(type, true, true); } else { evt = document.createEventObject(); evt.eventType = type; } evt.eventName = type; if (keyCode !== undefined){ evt.keyCode = keyCode; evt.which = keyCode; } if(document.createEvent) { element.dispatchEvent(evt); } else { element.fireEvent("on" + evt.eventType, evt); } } // clicking the comment link - it reveals the combobox document.querySelector(".fbTimelineSection .comment_link").click(); setTimeout(function(){ var combobox = document.querySelector(".fbTimelineSection [role='combobox']"); var spanWrapper = document.querySelector(".fbTimelineSection [role='combobox'] span"); // add text to the combobox spanWrapper.innerHTML = "<span data-text='true'>Thank you!</span>"; var spanElement = document.querySelector(".fbTimelineSection [role='combobox'] span span"); fireEvent("blur", combobox); fireEvent("focus", combobox); fireEvent("input", combobox); fireEvent("keydown", spanElement, 13); // pushing enter },2000);
function fireEvent(type, element) {
    var evt;

    if(document.createEvent) {
        evt = document.createEvent("HTMLEvents");
        evt.initEvent(type, true, true);
    } else {
        evt = document.createEventObject();
        evt.eventType = type;
    }

    evt.eventName = type;
    evt.keyCode = 13;
    evt.which = 13;

    if(document.createEvent) {
        element.dispatchEvent(evt);
    } else {
        element.fireEvent("on" + evt.eventType, evt);
    }
}

fireEvent('keydown', document.

要解決您的問題,您可能會看到此鏈接,有一個示例如何“使用 JavaScript 對 facebook 帖子自動評論”

“以下是步驟:

使用 m.facebook.com 轉到 Facebook 頁面 登錄並打開任何帖子。 通過按 Ctrl+Shift+I 導航到控制台,在 Chrome 中打開開發人員模式。 現在,運行以下腳本。”

var count = 100;
var message = "Hi";
var loop = setInterval(function(){
    var input = document.getElementsByName("comment_text")[0];
    var submit = document.querySelector('button[type="submit"]');
    submit.disabled = false;
    input.value = message;
    submit.click();
    count -= 1;
    if(count == 0)
    {
        clearInterval(loop);
    }
}, 10000);

親切的問候

參考: 源頁面

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM