Извлечение общедоступных постов со страницы Facebook без API/ ключа приложения / токена / секрета

Просто чтобы уточнить, у меня нет учетной записи Facebook, и я не собираюсь ее создавать. Кроме того, то, что я пытаюсь достичь, совершенно законно в моей стране.

Вместо того, чтобы использовать API Facebook для получения последних сообщений о времени на странице Facebook, я хочу отправить запрос на получение прямого доступа к URL-адресу страницы (например, этой странице) и извлечь сообщения из исходного кода HTML.
(Я хотел бы получить текст и время создания поста.)

Когда я запускаю это в веб-консоли:

document.getElementsByClassName('userContent')

Я получаю список элементов, содержащих текст последних постов.

Но я хотел бы извлечь эту информацию из скрипта nodejs. Я мог бы сделать это довольно легко с помощью браузера без головы, как puppeteer или тому подобное, но это создаст массу ненужных накладных расходов. Мне бы очень хотелось использовать простой подход, такой как загрузка кода HTML, передача его в cheerio и использование jQuery-подобного API cheeriio для извлечения сообщений.

Вот моя попытка попробовать именно это:

// npm i request cheerio request-promise-native
const rp = require('request-promise-native'); // requires installation of `request`
const cheerio = require('cheerio');

rp.get('https://www.facebook.com/pg/officialstackru/posts/').then( postsHtml => {
    const $ = cheerio.load(postsHtml);

    const timeLinePostEls = $('.userContent');
    console.log(timeLinePostEls.html()); // should NOT be null
    const newestPostEl = timeLinePostEls.get(0);
    console.log(newestPostEl.html()); // should NOT be null
    const newestPostText = newestPostEl.text();
    console.log(newestPostText);
    //const newestPostTime = newestPostEl.parent(??).child('.livetimestamp').title;
    //console.log(newestPostTime);
}).catch(console.error);

к несчастью $('.userContent') не работает. Тем не менее, я смог убедиться, что искомые данные встроены где-то в этот HTML-код.

Но я не мог придумать хороший подход к регулярным выражениям или тому подобное для извлечения этих данных.

В зависимости от содержимого сообщения количество тегов HTML в сообщении сильно варьируется.

Вот простой пример поста, содержащего одну ссылку:

<div class="_5pbx userContent _3576" data-ft="&#123;&quot;tn&quot;:&quot;K&quot;&#125;"><p>We&#039;re proud to be named one of Built In NYC&#039;s Best Places to Work in 2019, ranking in the top 10 for Best Midsize Places to Work and top 3 (!) for Best Perks and Benefits. See what it took to make the list and check out our profile to see some of our job openings. <a href="https://l.facebook.com/l.php?u=https%3A%2F%2Fbit.ly%2F2H3Kbr2&amp;h=AT29h2HyDsEk0rHRWqJA-Fa4M1qi3nJT1NBi95othaR3qeFuFAMNiVS2Dgtv5KR5m0xqjw6kfwZdhZt0_D3UQT1Oel2UhxRql-KwkA1xqWvrql4u1jDhzrkGVT_XxoUd8_w8_fzLZzzhz23a8yPCK6IPfWKB76_CEFjG3b78y4dFJvY9Z08AYlR01dmi5_FvWVEVytkN-123u6alYE8pqL6Jb6dtIQUTWGXYJPaNMrtxkCUZniEVXEcILkwHGSuHqCTAarboyMP55F1vhYO3OAiVMkvjbN274fVq92YvbK3bi90bU9T-5ADWHDUJ-CwcofSBTW47chstQeY0n_UluD_rBIPLsfXVSnCtpRkR2kXi9zzHLnNeIYeNssv3i7UKS_f5Z2pnVT6xe3zJbNpB68doH1Z__I9nsTCNIyFyKx2VxabecoL03DIawbRrzBoxLAwzNPLACBjTkpEQhdVn4_wdAIjXRL4cLQDcZkLEoG_sspBgRePH23TFbNufQOBly-FNtLHnkUDO2Ca-FYvAGXpcu6J4B1aH3XFPB803lsz-GRdACyOFOgXDXJfwr4WtWzUHxfiOPULWiI43yI5L4aU6wYRhPjxua3RuRZ8oj9fXa1w4Jrht94Ue2wfKtz8" target="_blank" data-ft="&#123;&quot;tn&quot;:&quot;-U&quot;&#125;" rel="noopener nofollow" data-lynx-mode="async">http://*******/2H3Kbr2</a></p></div>

Отформатированный в более читаемой форме, он выглядит примерно так:

<div class="_5pbx userContent _3576" data-ft="&#123;&quot;tn&quot;:&quot;K&quot;&#125;">
    <p>
        We&#039;re proud to be named one of Built In NYC&#039;s Best Places to Work in 
        2019, ranking in the top 10 for Best Midsize Places to Work and top 3 (!) for 
        Best Perks and Benefits. See what it took to make the list and check out our 
        profile to see some of our job openings.
        <a href="VERY_LONG_URL.........." target="_blank" data-ft="&#123;&quot;tn&quot;:&quot;-U&quot;&#125;" rel="noopener nofollow" data-lynx-mode="async">SHORT_LINK.....</a>
    </p>
</div>

Это регулярное выражение, кажется, работает хорошо, но я не думаю, что это очень надежно:

/<div class="[^"]+ userContent [^"]+" data-ft="[^"]+">(.+?)<\/div>/g

Если, например, запись содержит другой элемент div, он не будет работать должным образом. В дополнение к этому у меня нет никакого способа узнать время / дату, когда пост был создан с использованием этого подхода?

Любые идеи, как я мог бы относительно надежно извлечь последние 2-3 сообщения, включая дату / время создания?

1 ответ

Хорошо, я наконец понял это. Я надеюсь, что это будет полезно для других. Эта функция извлечет 20 последних сообщений, включая время создания:

// npm i request cheerio request-promise-native
const rp = require('request-promise-native'); // requires installation of `request`
const cheerio = require('cheerio');

function GetFbPosts(pageUrl) {
    const requestOptions = {
        url: pageUrl,
        headers: {
            'User-Agent': 'Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0'
        }
    };
    return rp.get(requestOptions).then( postsHtml => {
        const $ = cheerio.load(postsHtml);
        const timeLinePostEls = $('.userContent').map((i,el)=>$(el)).get();
        const posts = timeLinePostEls.map(post=>{
            return {
                message: post.html(),
                created_time: post.parents('.userContentWrapper').find('.timestampContent').html()
            }
        });
        return posts;
    });
}
GetFbPosts('https://www.facebook.com/pg/officialstackru/posts/').then(posts=>{
    // Log all posts
    for (const post of posts) {
        console.log(post.created_at, post.message);
    }
});

Поскольку сообщения Facebook могут иметь сложное форматирование, это не простой текст, а HTML. Но вы можете удалить форматирование и просто получить текст, заменив message: post.html() с message: post.text(),

Другие вопросы по тегам