見出し画像

プログラミングで推しクリエイターの新規投稿をGet!ポチッ

プログラミングで、
noteを使いやすくできるのでは?!


1ヶ月ほど前に読んだ
MitakaDaiさんの記事の内容が
頭を離れなくなりました。

詳細は記事を読んでいただきたいのですが、
簡単に概要を記載するとこんな感じです。

・noteは相互フォローが多い
・フォロー数が膨大になると、
 推しクリエイターの記事が埋もれる

この記事の後に、
半端ない分析記事を出されていて、
私の中では、

"分析の達人"

というイメージがつきました🤭

🌟 半端ない分析記事
【note】「フォロー戦略」と「フォロワー数」「スキ数」との関係性


もともとは本田すのうさんが、

「推しの記事は毎日見たいけれども、
 推しの最新記事が"フォロー中"のタブに
 埋もれてて気がつかないことがある。」

というお悩みを
話されていたことからはじまりました。


1ヶ月間、
モヤモヤしていたのですが、
昨日ひらめきました。


プログラミングで
推しクリエイターの記事を
出せないか?


というわけで、作ったのがこちらです

Chromeの拡張機能というのを使っています。

右上のボタンを押すと、
フォロー中のページに表示されている
推しクリエイターの記事を抽出してくれます。

Chrome拡張機能というのは、
簡単に自作できて使い勝手がとても良いです。

作り方は、
インターネットの記事のほうが詳しいので、
この記事では概要だけお伝えします。

Chrome拡張機能は、
4つのファイル構成となってます。

  • manifestファイル (権限や初期画面等の設定)

  • HTMLファイル (画面表示)

  • JavaScriptファイル (プログラム)

  • Imageファイル (アイコン)


プログラムの流れと合わせて、
簡単にご紹介します。


まずは、
manifestファイルです。

ここでは権限の設定や、
アイコンクリック時に開くHTMLファイルを
指定しています。

以下、実際のコードです。

・manifest.json

{
  "manifest_version": 3,
  "name": "Data Fetcher",
  "version": "1.0",
  "permissions": [
    "activeTab",
    "tabs",
    "scripting",
    "storage"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  },
  "icons": {
    "48": "icon.png"
  },
  "host_permissions": ["http://*/*", "https://*/*"]
}

上記の"default_popup"という設定で、
popup.htmlを設定しています。

これにより、
右上のボタンを押すと、
ポップアップの画面が呼び出されています。

ポップアップ画面を構成しているファイルは
ホームページを制作したことがある方なら、
馴染みのあるHTMLです。

・popup.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Fetch Data</title>
  <style>
    body { width: 300px; }
    button { margin: 20px; }
  </style>
</head>
<body>
  <button id="fetchData">推しメンタイムライン確認</button>
  <script src="popup.js"></script>
</body>
</html>

とてもシンプルです。

<button>タグでボタンを表示して、
押された場合にpopup.jsを呼び出します。


popup.jsのコードはこちら。

popup.js

document.getElementById('fetchData').addEventListener('click', () => {

  const initialUrl = "https://note.com/following";

  chrome.tabs.query({ url: initialUrl }, (tabs) => {
    if (tabs.length > 0) {
        // URLが既に開かれている場合、そのタブをアクティブにする
        chrome.tabs.update(tabs[0].id, { active: true });
        console.log('Tab created, ID: ' + tabs[0].id);
        chrome.runtime.sendMessage({ action: 'fetchData', tabId: tabs[0].id });
    } else {
        // URLが開かれていない場合、新しいタブで開く(未実装)
        // chrome.tabs.create({ url: initialUrl });
        // chrome.runtime.sendMessage({ action: 'fetchData', tabId: tab.id });
    }
});
});

popup.htmlから呼び出されて、
フォロー中のページ(https://note.com/following)の
表示あり/なしを確認します。

表示されていればその画面を利用し、
表示されていなければ新規にページを開きます。

今回は試しで作ったので、
表示されている画面を利用するパターンだけを
実装しました。


"sendMessage"という処理に入ると、
manifest.jsonで設定していた"service_worker"
という設定のファイルを呼び出します。

・manifest.json

  "background": {
    "service_worker": "background.js"

呼び出されるのは、
設定されているbackground.jsとなります。

実際のコードを載せますが、
かなり長くなってます。

作りたい方向けに全部載せてますので、
説明を読みたい方はスキップしてください。

・background.js

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'fetchData') {
    chrome.scripting.executeScript(
      {
        target: { tabId: request.tabId },
        function: fetchDataFromNote
      },
      (result) => {
        if (chrome.runtime.lastError) {
          console.error('Script execution failed:', chrome.runtime.lastError.message);
          return;
        }

        if (Array.isArray(result) && result.length > 0 && result[0].result) {
          const fetchedData = result[0].result;
          console.log('Script executed, result:', fetchedData);

          // データをループして処理する
          fetchedData.forEach(data => {
            console.log('Fetched Data:', data);
            // ここでデータの処理を行う(例: データを保存、表示など)
          });

          chrome.storage.local.set({ fetchedData: fetchedData });
          chrome.tabs.create({ url: 'data.html' });
        } else {
          console.error('No valid data returned from script execution');
        }
      }
    );
  }
});

function fetchDataFromNote() {
  const targetStrings = ["クロサキナオ", "lion", "みかん", "MitakaDai"]; // 複数の文字列を配列に設定
  const figures = document.querySelectorAll('#__layout > div > div:nth-child(1) > div:nth-child(3) > div > div.t-timeline-new__body > div.p-4.sm\\:px-6.sm\\:pt-1.sm\\:pb-6 > div.sm\\:hidden > figure');

  const data = Array.from(figures)
    .map(figure => {
      const spanElement = figure.querySelector('div.o-horizontalTimeLineNote__body > div.o-horizontalTimeLineNote__content.o-horizontalTimeLineNote__content--horizontal > div > div > div.o-horizontalTimeLineNote__user > a > span');
      const aElement = figure.querySelector('a');

      const spanText = spanElement ? spanElement.innerText : null;
      const aText = aElement ? aElement.href : null;

      return { spanText, aText };
    })
    .filter(item => (item.spanText !== null || item.aText !== null) &&
      (targetStrings.some(target => (item.spanText && item.spanText.includes(target))) || targetStrings.some(target => (item.aText && item.aText.includes(target)))));

  return data;
}

フォロー中のページから、
気になるクリエイターの方を抽出します。

クリエイターの方は、
こんな感じで定義しています。

const targetStrings = ["クロサキナオ", "lion", "みかん", "MitakaDai"]; // 複数の文字列を配列に設定


どのようにフォロー中の画面から
抽出するかというと、
セレクタという仕様を使います。

セレクタは、
WEBページで指をさしたところから
データを取得するイメージです。

まず、
クロサキナオさんの枠全体を指さします。

枠全体を指さししたら、
次に"名前"と"URL"を2つセットで取得します。

この処理を推しメン全員分実行し、
最後に結果を画面に表示してあげます。

表示先はdata.htmlとしました。

chrome.tabs.create({ url: 'data.html' });

data.htmlもシンプルな実装ですが、
取得したデータを成型するため、
data.jsを呼び出すようにしています。

・data.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Fetched Data</title>
  <script src="data.js"></script>
</head>
<body>
  <h1>推しメンタイムライン更新リスト</h1>
  <ul id="dataList"></ul>
</body>
</html>

data.jsを使い、
"名前"と"URL"を分けて画面表示するよう
設定し直してしています。

・data.js

document.addEventListener('DOMContentLoaded', () => {
    chrome.storage.local.get('fetchedData', (result) => {
      const dataList = document.getElementById('dataList');
      const fetchedData = result.fetchedData || [];
  
      fetchedData.forEach(item => {
        const listItem = document.createElement('li');
        listItem.textContent = `名前: ${item.spanText || 'N/A'}, URL: ${item.aText || 'N/A'}`;
        dataList.appendChild(listItem);
      });
    });
  });

結果、
最終的にはこのような画面が表示されます。

抽出対象としていた
みかんさんMitakaDaiさんは、
ツールを動かした際に
直近で投稿をしていなかったため、
抽出されていません。

クロサキナオさんとlionさんは、
直近で投稿をしていたので表示されました。


ただ、
フォロー中のページには、
50〜60件程度しか初期表示されていないので、
抽出可能な量が少ないです。

ページ内で下に何回かスクロールすると、
多く記事が表示されるので良いかもしれませんね。

まだ改善の余地はありますが、
いったん基礎は出来上がりました。


もしも作成してみたい方は、
この記事にプログラムを載せていますので、
下記の通り1つのフォルダに配置して、
Chrome拡張機能に読み込ませてみてください。

*icon.pngは下記をご利用ください。
 48px × 48pxならなんでもOKです。


しかし、
ここで重要なことに気づきます。


noteって
スマホで使う人が多いのでは?


電車の中とかの空いてる時間で、
読みたいですもんね。

スマホで改良版を作ろうと思っていた矢先。

調べていると、こんな記事が。


noteアプリでクリエイターの更新通知を受け取れます

なになに…?


「noteアプリを使えば、
 推しクリエイターの記事が新規投稿された時に、
 通知がくるヨ。」











昨日の実装3〜4時間は
いったいなんだったのか


2023年9月にできていた機能だったとは。
1年作るのが遅かったですね笑


いかがでしたでしょうか。

みなさんも、
なにかに着手される前は
ちゃんと調べてからにしましょう🤣

でも、
推しクリエイターの新規投稿以外にも
便利にできる要素もあるかもしれませんので、
今後もアイデアがあれば何か作ってみたいと思ってます。


ばーこしってどんな人?



いただいたサポートは人の笑顔のために利用させていただきます。