Извлечение общедоступных постов со страницы 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="{"tn":"K"}"><p>We're proud to be named one of Built In NYC'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&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="{"tn":"-U"}" rel="noopener nofollow" data-lynx-mode="async">http://*******/2H3Kbr2</a></p></div>
Отформатированный в более читаемой форме, он выглядит примерно так:
<div class="_5pbx userContent _3576" data-ft="{"tn":"K"}">
<p>
We're proud to be named one of Built In NYC'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="{"tn":"-U"}" 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()
,