You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Gatsby项目的JavaScript代码中使用本地TXT文件填充体育赛事表格

如何在Gatsby中使用本地TXT文件数据渲染体育赛事表格?

问题描述

我用MechanicalSoup(Python库)爬取了学校网站的体育赛事数据,生成了两个TXT文件:upcomingFixturesData.txt和resultsFixturesData.txt,每行格式如下:

22/03/2022 4:15pm Hockey Hockey v SchoolName: U16 (a, leave at 3.00pm)
22/03/2022 10:00am Fives Fives National Championships: U18 (SchoolName, leave at 9.00am)
22/03/2022 4:00pm Netball Netball: Leavers v Common Room (h)

目前我的Gatsby组件里用的是模拟数据渲染表格,之前处理JSON格式的课程表时,我可以直接用map方法遍历渲染。现在想知道能不能用同样的map方法处理这两个TXT文件?如果不行,还有什么其他方法可以在JavaScript代码中使用这些本地TXT数据?


回答

当然可以用map方法处理这些TXT文件!不过首先得把纯文本格式的内容转换成结构化的JavaScript数组对象——毕竟map是用来遍历数组的,直接对字符串用不了。下面给你两种实用的方法,适配Gatsby的场景:

方法一:直接在组件中解析TXT文件(适合静态数据)

这种方法最简单,适合数据不常更新的情况,利用Webpack的资源加载能力直接导入TXT文件,然后解析成数组对象:

  1. 将TXT文件放在项目目录:比如放在src/data/scraped/下(和你之前的JSON文件同目录)。

  2. 编写解析函数:把TXT字符串转换成包含赛事信息的对象数组:

function parseFixtures(txtContent) {
  // 按行拆分,过滤空行
  return txtContent.split('\n').filter(line => line.trim() !== '').map(line => {
    // 拆分每行:前三个元素是日期、时间、项目,剩余部分合并为赛事详情
    const [date, time, sport, ...subtitleParts] = line.split(/\s+/);
    return {
      date,
      time,
      title: sport,
      subtitle: subtitleParts.join(' ')
    };
  });
}
  1. 在组件中导入并渲染:
import upcomingTxt from '../../data/scraped/upcomingFixturesData.txt';
import resultsTxt from '../../data/scraped/resultsFixturesData.txt';
import Wrapper from './your-wrapper-component'; // 替换成你的实际组件
import RowWrapper from './your-row-wrapper-component';
import Row from './your-row-component';
import Description from './your-description-component';

export default function SportsSection() {
  const upcomingFixtures = parseFixtures(upcomingTxt);
  const resultsFixtures = parseFixtures(resultsTxt);

  return (
    <Wrapper>
      {/* 即将到来的赛事 */}
      <RowWrapper>
        <Description>Upcoming Fixtures</Description>
        {upcomingFixtures.map((item, index) => (
          <Row 
            key={index}
            number={index + 1} 
            title={item.title} 
            subtitle={item.subtitle} 
            time={item.time} 
          />
        ))}
      </RowWrapper>

      {/* 已结束的赛事结果 */}
      <RowWrapper>
        <Description>Recent Results</Description>
        {resultsFixtures.map((item, index) => (
          <Row 
            key={index}
            number={index + 1} 
            title={item.title} 
            subtitle={item.subtitle} 
            time={item.time} 
          />
        ))}
      </RowWrapper>
    </Wrapper>
  )
}

方法二:用Gatsby的数据源系统处理(适合需要GraphQL或动态更新的场景)

如果你的赛事数据会定期更新,或者想利用Gatsby的GraphQL数据层,推荐用这种方法,在构建时解析TXT文件并生成可查询的节点:

  1. 安装依赖插件:
npm install gatsby-source-filesystem
  1. 配置gatsby-config.js:让Gatsby读取TXT文件所在目录:
module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `fixtures`,
        path: `${__dirname}/src/data/scraped/`,
      },
    },
  ],
}
  1. 编写gatsby-node.js解析TXT文件:在构建时将TXT内容转换成结构化数据:
exports.onCreateNode = ({ node, actions }) => {
  const { createNodeField } = actions;
  // 只处理TXT文件
  if (node.internal.type === `File` && node.extension === `txt`) {
    const fs = require('fs');
    const content = fs.readFileSync(node.absolutePath, 'utf8');
    // 判断是即将到来的赛事还是结果
    const fixtureType = node.name.includes('upcoming') ? 'upcoming' : 'results';

    // 解析内容成对象数组
    const fixtures = content.split('\n').filter(line => line.trim() !== '').map(line => {
      const [date, time, sport, ...subtitleParts] = line.split(/\s+/);
      return {
        date,
        time,
        title: sport,
        subtitle: subtitleParts.join(' ')
      };
    });

    // 添加自定义字段到文件节点
    createNodeField({
      node,
      name: `fixtureType`,
      value: fixtureType,
    });
    createNodeField({
      node,
      name: `fixtures`,
      value: fixtures,
    });
  }
};
  1. 在组件中用GraphQL查询并渲染:
import { graphql } from 'gatsby';
import Wrapper from './your-wrapper-component';
import RowWrapper from './your-row-wrapper-component';
import Row from './your-row-component';
import Description from './your-description-component';

export const query = graphql`
  query FixturesQuery {
    upcoming: file(name: {eq: "upcomingFixturesData"}) {
      fields {
        fixtures {
          date
          time
          title
          subtitle
        }
      }
    }
    results: file(name: {eq: "resultsFixturesData"}) {
      fields {
        fixtures {
          date
          time
          title
          subtitle
        }
      }
    }
  }
`;

export default function SportsSection({ data }) {
  const upcomingFixtures = data.upcoming.fields.fixtures;
  const resultsFixtures = data.results.fields.fixtures;

  return (
    <Wrapper>
      <RowWrapper>
        <Description>Upcoming Fixtures</Description>
        {upcomingFixtures.map((item, index) => (
          <Row 
            key={index}
            number={index + 1} 
            title={item.title} 
            subtitle={item.subtitle} 
            time={item.time} 
          />
        ))}
      </RowWrapper>
      <RowWrapper>
        <Description>Recent Results</Description>
        {resultsFixtures.map((item, index) => (
          <Row 
            key={index}
            number={index + 1} 
            title={item.title} 
            subtitle={item.subtitle} 
            time={item.time} 
          />
        ))}
      </RowWrapper>
    </Wrapper>
  )
}

注意事项

  • 解析逻辑要根据你的TXT格式调整:如果后续赛事行的格式有变化(比如项目名称包含空格),需要修改split的规则,比如用更精准的正则表达式拆分。
  • 第一种方法适合小型、静态的数据;第二种方法更适合数据需要更新或需要和其他Gatsby数据源整合的场景。

内容的提问来源于stack exchange,提问作者roshpro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 16:02:45