paint-brush
如何使用 API 和 GitHub Actions 创建仪表板来跟踪您的 Twitter/X 关注者统计信息经过@horosin
336 讀數
336 讀數

如何使用 API 和 GitHub Actions 创建仪表板来跟踪您的 Twitter/X 关注者统计信息

经过 Karol Horosin14m2024/07/09
Read on Terminal Reader

太長; 讀書

在本文中,我讨论了如何创建一个指标仪表板来跟踪 Twitter 参与度和关注者统计数据,旨在为目标设定和问责提供切实可行的指标。我分享了有关设置 Twitter 开发者帐户、使用 Node.js 获取数据、将数据保存在 GitHub 存储库中以及使用 Chart.js 通过简单的 HTML 仪表板呈现数据的详细信息。该过程包括编写用于数据获取和保存的脚本、设置 GitHub Actions 以实现自动化以及在 GitHub Pages 上部署仪表板。提供了完整的代码和教程链接,可免费自动跟踪社交媒体指标。
featured image - 如何使用 API 和 GitHub Actions 创建仪表板来跟踪您的 Twitter/X 关注者统计信息
Karol Horosin HackerNoon profile picture

我喜欢为我的目标设定切实可行的指标。理想情况下,这些指标会被自动跟踪,并且会有一个机制来监督我。


我今年的目标之一是发表更多文章,更加公开地介绍我的工作方式以及我在我的专业领域中发现的有趣之处。我可以为此附加什么指标?一个当然是文章数量;另一个可能是有多少人觉得它们有趣到足以关注我。


为了了解这些指标随时间的变化情况,我决定创建一个小型仪表板来跟踪它们的历史值。我决定从 X/Twitter 开始。


在此处查看本教程中创建的仪表板: https://horosin.github.io/metrics-dashboard/


完整代码:https://github.com/horosin/metrics-dashboard


您可能听说过 X 去年限制了对其 API 的访问。他们确实这样做了,但他们仍然允许我们访问我们自己的基本指标(与 LinkedIn 等平台相反 - 微软真丢脸;我必须爬取数据才能访问我的数据)。

我们要构建什么

需要编写/配置一些软件:


  • 从 X 获取数据的代码。


  • 将数据保存在某处的脚本(在本例中,保存在 GitHub 存储库中的 JSON 文件中)。


  • 安排定期运行代码 - 每天的给定时间。


  • 用于呈现数据的仪表板(使用 chart.js 的简单单个 HTML 文件)。


  • GitHub Pages 用于托管仪表板。


最好的部分是我们可以免费完成所有这些工作(包括计算)。

设置

Twitter 应用程序

在开发人员部分设置 Twitter 应用程序是访问 Twitter API 的先决条件,这对于获取关注者数量等数据、发布推文或以编程方式访问其他 Twitter 资源至关重要。以下是帮助您入门的分步指南。


  1. 导航到 Twitter 开发者网站:转到Twitter 开发者,然后使用您的 Twitter 帐户登录。如果您没有 Twitter 帐户,则需要创建一个。完成申请/注册。


  2. 转到开发者仪表板:访问您的Twitter 开发者仪表板


  3. 创建项目:点击“创建项目”。系统将要求您提供项目名称、描述和用例。根据项目需求填写这些信息。


  4. 在您的项目中创建应用程序:创建项目后,您可以选择在此项目中创建应用程序。单击“创建应用程序”,然后填写必要的详细信息,例如应用程序名称。


  5. 获取 API 密钥和令牌:创建应用后,您将被引导至包含应用详细信息的页面,包括 API 密钥、API 密钥、访问令牌和访问令牌密钥。请安全保存这些凭据;您将需要它们来验证您对 Twitter API 的请求。

项目

现在,让我们开始编码。在系统上创建一个新目录,然后在那里打开一个控制台。


 mkdir metrics-dashboard cd metrics-dashboard


确保初始化 Git 存储库,然后将其连接到 GitHub 项目。


初始化 node.js 项目,并安装一些我们需要使用 API 进行身份验证的包。


 npm init npm i dotenv oauth-1.0a crypto


使用之前从 X 获取的所有密钥创建一个.env文件。请勿将其提交到存储库。这只是为了在本地测试脚本。


 TWITTER_API_KEY='' TWITTER_API_SECRET='' TWITTER_ACCESS_TOKEN='' TWITTER_ACCESS_SECRET=''


创建.gitignore文件以避免这种情况。下面的示例包含我们想要忽略的其他路径。


 node_modules/ .env .DS_Store dashboard/data/


获取数据

首先,我们将编写一个名为的 Node.js 脚本,用于从平台的 API 中获取关注者统计信息。我们将使用标准获取库进行 API 调用,并使用oauth-1.0a与 X 进行身份验证。获取数据后,我们将结果写入 JSON 文件,该文件将用作我们的数据库。


这将由单独的脚本处理。为了使其可以访问输出,我们将把它写入 GitHub Actions 中可用的环境文件中。


我正在使用节点 20。


在我们的项目根目录中创建一个名为x_fetch_data.js的文件。


 require('dotenv').config(); const OAuth = require('oauth-1.0a'); const crypto = require('crypto'); const fs = require('fs'); // Initialize OAuth 1.0a const oauth = OAuth({ consumer: { key: process.env.TWITTER_API_KEY, // Read from environment variable secret: process.env.TWITTER_API_SECRET // Read from environment variable }, signature_method: 'HMAC-SHA1', hash_function(base_string, key) { return crypto.createHmac('sha1', key).update(base_string).digest('base64'); } }); const token = { key: process.env.TWITTER_ACCESS_TOKEN, // Read from environment variable secret: process.env.TWITTER_ACCESS_SECRET // Read from environment variable }; const url = 'https://api.twitter.com/2/users/me?user.fields=public_metrics'; const fetchTwitterFollowerCount = async () => { const requestData = { url, method: 'GET', }; // OAuth header const headers = oauth.toHeader(oauth.authorize(requestData, token)); headers['User-Agent'] = 'v2UserLookupJS'; const response = await fetch(url, { method: 'GET', headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log(data); // Extract the metrics const metrics = data?.data?.public_metrics; // Write the metrics to the environment file fs.appendFileSync(process.env.GITHUB_OUTPUT, `METRICS=${JSON.stringify(metrics)}\n`); }; fetchTwitterFollowerCount().catch(err => console.error(err));


要测试脚本,您可以运行:


 GITHUB_OUTPUT=testoutput node x_fetch_data.js


您应该在输出以及testoutput文件中看到您的 X 指标:


 metrics={"followers_count":288,"following_count":302,"tweet_count":1381,"listed_count":0,"like_count":591}


保存数据

要保存数据,请在文件x_save_data.js中创建另一个脚本。它将获取环境中的输出并将其附加到./data/x.json


确保先创建此文件并将其提交到 git 存储库。它应该有一个空数组作为其内容。


 []


如果当天已经获取了数据,脚本也不会添加重复记录。它会覆盖旧记录。


 const fs = require('fs'); // Parse the JSON string from the environment variable const metrics = JSON.parse(process.env.METRICS); const path = './data/x.json'; const now = new Date(); const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`; let data = []; if (fs.existsSync(path)) { data = JSON.parse(fs.readFileSync(path)); } const todayIndex = data.findIndex(entry => entry.date === today); if (todayIndex > -1) { data[todayIndex] = { date: today, ...metrics }; } else { data.push({ date: today, ...metrics }); } fs.writeFileSync(path, JSON.stringify(data, null, 2));


您可以通过编辑 testouput 文件来测试脚本,在 JSON 周围添加单引号,然后运行以下命令。根据需要编辑文件,因为 GitHub Actions 环境的行为不同并且不需要引号。


 # load output from the previous script set -a; source testoutput; set +a; node x_save_data.js


预定的 GitHub 操作


现在,让我们创建一个包含 GitHub 操作代码的文件。它将每天在指定时间运行并获取我们的指标。然后它将保存它们并将它们提交到存储库。


将以下代码保存在.github/workflows/fetch_x_data.yml下。


 name: Fetch X Data on: schedule: # Runs at 4 AM UTC - cron: '0 4 * * *' workflow_dispatch: # This line enables manual triggering of the action jobs: fetch_data: runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - name: Check out the repository uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: "20" - name: Install dependencies run: npm install - name: Fetch Data from Platform X id: fetch_data run: node x_fetch_data.js env: TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY }} TWITTER_API_SECRET: ${{ secrets.TWITTER_API_SECRET }} TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} TWITTER_ACCESS_SECRET: ${{ secrets.TWITTER_ACCESS_SECRET }} - name: Save data run: node x_save_data.js env: METRICS: ${{ steps.fetch_data.outputs.METRICS }} - name: Commit and push if there's changes run: | git config --global user.email "[email protected]" git config --global user.name "GitHub Action" git add data/x.json git commit -m "Update data for Platform X" || exit 0 # exit 0 if no changes git push


通过提交代码,然后转到 GitHub 上项目的“操作”部分并从那里触发它,手动运行该操作。

仪表板

好的,如何呈现数据?我不想摆弄简单的 HTML,所以我让 ChatGPT 帮我生成数据。


dashboard文件夹中创建一个index.html文件。我们不使用项目的主目录,以避免将数据获取代码与 HTML 一起托管。


 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Twitter Dashboard</title> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <style> body { font-family: Arial, sans-serif; margin: 0; padding: 0; display: flex; flex-direction: column; align-items: center; } .chart-container { width: 80%; max-width: 1000px; } canvas { max-width: 100%; } h1 { text-align: center; margin-top: 20px; } h2 { text-align: center; margin-top: 20px; } </style> </head> <body> <h1>Twitter Dashboard</h1> <h2>Number of Followers</h2> <div class="chart-container"> <canvas id="followersChart"></canvas> </div> <h2>Number of Tweets</h2> <div class="chart-container"> <canvas id="tweetsChart"></canvas> </div> <script> fetch('data/x.json') .then(response => response.json()) .then(data => { const dates = data.map(item => item.date); const followers = data.map(item => item.followers_count); const tweets = data.map(item => item.tweet_count); const minFollowers = Math.min(...followers) - 100; const minTweets = Math.min(...tweets) - 100; const followersCtx = document.getElementById('followersChart').getContext('2d'); const tweetsCtx = document.getElementById('tweetsChart').getContext('2d'); new Chart(followersCtx, { type: 'line', data: { labels: dates, datasets: [{ label: 'Followers', data: followers, backgroundColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: false, min: minFollowers } } } }); new Chart(tweetsCtx, { type: 'line', data: { labels: dates, datasets: [{ label: 'Tweets', data: tweets, backgroundColor: 'rgba(255, 99, 132, 0.2)', borderColor: 'rgba(255, 99, 132, 1)', borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: false, min: minTweets } } } }); }); </script> </body> </html>


将其提交到存储库。


(可选)如果您想在本地进行测试,请将数据文件夹复制到仪表板文件夹并在其中启动一个简单的服务器。


 cp -r data dashboard/ cd dashboard # start server with Python if you have it installed (version 3) # otherwise, use other way eg https://gist.github.com/willurd/5720255 python -m http.server 8000


将仪表板部署到 GitHub Pages

现在我们有了仪表板,是时候将其呈现到网络上了!


如果您使用的是 GitHub 上的免费帐户,您的页面以及整个存储库都需要公开。


创建一个.github/workflows/deploy_dashboard.yml文件。


 name: Deploy to GitHub Pages on: schedule: # redeploy after data update - cron: '0 5 * * *' push: branches: - main workflow_dispatch: # This line enables manual triggering of the action permissions: contents: read pages: write id-token: write # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: "pages" cancel-in-progress: false jobs: deploy: permissions: pages: write # to deploy to Pages id-token: write # to verify the deployment originates from an appropriate source environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v4 - name: Copy data to dashboard folder run: cp -r data dashboard/ - name: Update pages artifact uses: actions/upload-pages-artifact@v3 with: path: dashboard/ - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 # or specific "vX.XX" version tag for this action


该操作应部署该页面。您可以在 GitHub 项目设置中或工作流输出中的“操作”部分中找到 URL。


再次,您可以在这里找到我的: https://horosin.github.io/metrics-dashboard/

概括

就这样!一个完整的自动化系统,用于跟踪您的社交媒体 (X) 指标、自动获取数据、保存历史数据并可视化趋势。通过此设置,您可以将功能扩展到其他平台和指标,从而创建一个满足您所有分析需求的综合仪表板。如果您想了解这方面的内容,请告诉我。


通过在左侧填写您的电子邮件地址来订阅我的个人资料,并及时了解我的文章!

不要忘记在 Twitter 上关注我@horosin ,并订阅我的博客新闻通讯以获取更多提示和见解!


如果您没有 Twitter,您也可以在LinkedIn上关注我。