プログラミング

Facebookのfeedが取得できない時の回避策-nodejs

スポンサーリンク
TOTTI

TOTTI

Facebookの公開フィードを取得して、色々なところからデータを集めたいスクレイピングしたいという需要はあるだろう。

facebookページのフィードを取得しよう!(難あり)

一般的な、facebookページのフィードの取得は、facebookのgraphAPIでデータを取得することが可能であり。以下の記事が参考になる。

だが、facebookのページフィードをFacebookGraphAPI経由で扱うには結構厄介な条件がある。

As of April 30, 2018, the source field for /page/feed and /page/posts will no longer be returned for Page-owned videos unless the User making the request has a role on the owning Page.

公式レファレンスhttps://developers.facebook.com/docs/graph-api/reference/v3.2/page/feed

要するにだ・・・権限を持っていないfacebookフィードにはアクセスできないということである。

  • 取得するfacebookページを保有していることor権限があること
  • App申請およびレビューが通っていること

2018年4月30日以降、セキュリティ面が強化されており、今後も取得はさせてくれないと思われる。

FacebookPageのfeedにアクセスするのは、ちょっと難ありといえます。

仕方ないので、facebookのwebスクレイピングを行い必要な情報を集める必要があります。

 

スポンサーリンク

facebookページのWebスクレイピングをしよう!

前述したように、Api経由でのfeed取得は諦める必要が出てくる。その場合は、ウェブスクレイピングをする方法しかなくなる。最近はgoogleがchromeのgui無しの動作ができるheadlessChromeを出してくれている。最近のwebスクレイピングは、これ一択である(少し重い)

Facebookページは、Javascriptを多用しているので、HeadlessChrome必須である。

その他ヘッドレスブラウザには下記があるようだ。

ヘッドレスブラウザの種類

ヘッドレスブラウザ

実装 名前 実行時間(s) 総評
chrome Headles Chrome 1.5〜2.5 今から使うならこれ。開発リソースの安心感
Electoron Nightmare 1.5〜2.5 Headles Chromeと大差はない。無理して乗り換える必要はない
独自実装 PhantomJS 4.3〜4.8 性能と開発リソースに難あり。使い続けるのは厳しい

参考:  https://qiita.com/ledsun/items/0965a60f9bdff04f2fa0

nodejs: headlessChormeをインストール

基本的には、puppeteerをインストールすると自動的にインストールされる。

https://www.npmjs.com/package/puppeteer

https://github.com/GoogleChrome/puppeteer

npm install puppeteer

出典:stackoverflow

実際にインストールすると、結構依存しているライブラリが多いようで色々と追加でインストールが必要だった。

facebookのページをスクレイピングするにはスクロールが必要。

facebookのページに関してスクレイピングをかける時には、無限スクロールが存在しているので、スクロールの機能を入れないと欲しいデータが取得できない。

具体的なやり方は、下記のサイトを参考にするのが良い。

https://intoli.com/blog/scrape-infinite-scroll/

とても簡潔なソースなので、改造もしやすくとてもいいw中の要素の個数指定もできるのが素晴らしい。

実際にfacebookページにあるアイテム10個が出現するまでスクロールしてhtmlを出力するソースは下記。nodejs完全なソースではないが,クラスの「._6ks」を10個取り出すまで、スクロールする感じ。

今回改造したソースの抜粋
[highlight_javascript]

function extractItems() {
const extractedElements = document.querySelectorAll(‘._6ks’);
const items = [];
for (let element of extractedElements) {
 var u = String(element.innerHTML);
items.push(u);
}
return items;
}

async function scrapeInfiniteScrollItems(
page,
extractItems,
itemTargetCount,
scrollDelay = 1000,
) {
let items = [];
try {
let previousHeight;
while (items.length < itemTargetCount) {
items = await page.evaluate(extractItems);
previousHeight = await page.evaluate(‘document.body.scrollHeight’);
await page.evaluate(‘window.scrollTo(0, document.body.scrollHeight)’);
await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`);
await page.waitFor(scrollDelay);
}
} catch(e) { }
return items;
}

const getfbp = async(url,res)=>{
const browser = await puppeteer.launch({
headless: true,
args: [‘–no-sandbox’, ‘–disable-setuid-sandbox’],
});
const page = await browser.newPage();

page.setViewport({ width: 1280, height: 926 });

await page.goto(url);

const items = await scrapeInfiniteScrollItems(page, extractItems, 10);

let bodyHTML = await page.evaluate(() => document.body.innerHTML);
res.send(bodyHTML);

await browser.close();
};
[/highlight_javascript]

おそらく、重要になる部分は

ランチ時のオプション設定

args: [‘–no-sandbox’, ‘–disable-setuid-sandbox’],

facebookページのエレメント指定部分

const extractedElements = document.querySelectorAll(‘._6ks’);

以上。