<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ 自动化 - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ freeCodeCamp 是一个免费学习编程的开发者社区，涵盖 Python、HTML、CSS、React、Vue、BootStrap、JSON 教程等，还有活跃的技术论坛和丰富的社区活动，在你学习编程和找工作时为你提供建议和帮助。 ]]>
        </description>
        <link>https://www.freecodecamp.org/chinese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ 自动化 - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/chinese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 23 Jun 2026 04:17:05 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/chinese/news/tag/automation/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 如何使用 GitHub Actions 实现开源项目的自动化 ]]>
                </title>
                <description>
                    <![CDATA[ 如今，开发人员经常使用自动化工具来有效地管理任务，并简化他们的日常活动。GitHub Actions 就是这些流行的工具之一。 你可能会同意我的观点：软件（包括开源软件）对效率的要求很高。在这种自动化工具的帮助下，维护者可以将重复性的工作自动化，并专注于更重要的任务，如编写高质量的代码、审核贡献，以及围绕项目创建一个活跃的社区。 我曾经不得不手动完成一些本可以自动化的任务，所以我觉得我有资格分享如何使用 GitHub Actions 来节省时间。 我花了大半天的时间去研究我的一个已经吸引了贡献者的迷你 Python 项目 [https://github.com/larymak/Python-project-Scripts]。我给新的贡献者写热情洋溢的欢迎词，检查最近 pull requests，以确保他们遵守项目的规则比如 README 文件和说明、如果需要的话提供截图，等等。 但我不知道的是，我可以自动执行其中一些任务以及更多任务，以减少自己的工作量。我可以在 GitHub Actions 的帮助下做到这一点。 在本指南中，我将分享更多关于 GitHub Actions 的 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/automate-open-source-projects-with-github-actions/</link>
                <guid isPermaLink="false">64257c76e32a7606487d5e9f</guid>
                
                    <category>
                        <![CDATA[ 开源 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 自动化 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Thu, 30 Mar 2023 10:21:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2023/03/OOP--4-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/automate-open-source-projects-with-github-actions/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Use GitHub Actions to  Automate Open-Source Projects</a>
      </p><p>如今，开发人员经常使用自动化工具来有效地管理任务，并简化他们的日常活动。GitHub Actions 就是这些流行的工具之一。</p><p>你可能会同意我的观点：软件（包括开源软件）对效率的要求很高。在这种自动化工具的帮助下，维护者可以将重复性的工作自动化，并专注于更重要的任务，如编写高质量的代码、审核贡献，以及围绕项目创建一个活跃的社区。</p><p>我曾经不得不手动完成一些本可以自动化的任务，所以我觉得我有资格分享如何使用 GitHub Actions 来节省时间。</p><p>我花了大半天的时间去研究我的一个已经吸引了贡献者的<a href="https://github.com/larymak/Python-project-Scripts">迷你 Python 项目</a>。我给新的贡献者写热情洋溢的欢迎词，检查最近 pull requests，以确保他们遵守项目的规则比如 README 文件和说明、如果需要的话提供截图，等等。</p><p>但我不知道的是，我可以自动执行其中一些任务以及更多任务，以减少自己的工作量。我可以在 GitHub Actions 的帮助下做到这一点。</p><p>在本指南中，我将分享更多关于 GitHub Actions 的信息，以及我如何使用它。我将向你展示如何利用它来自动化项目的各个方面，从欢迎新贡献者到分配任务、检查代码质量等等。我们一起来让你的项目更加高效、更具有交互性。</p><h2 id="github-actions-"><strong>GitHub Actions 是什么</strong></h2><p>GitHub Actions 是一种工具，可让你在 GitHub 仓库中执行不同的自动化操作。它允许你创建自定义工作流，你可以使用这些工作流来自动化开发过程，例如构建、测试和部署代码。</p><p>将此工具与其他 GitHub 功能集成后，你可以转变你的项目管理程序，让每个参与其中的人都更加愉快，更加有参与感。</p><h3 id="-github-actions"><strong>如何在你的仓库中设置 GitHub Actions</strong></h3><p>一切都从根文件夹开始。默认情况下，GitHub Actions 通常集成在你的 GitHub 仓库中，因此你无需在安装时注册单独的账户。但是你需要执行几个步骤才能访问它的功能。</p><ul><li>在你的 GitHub 仓库中，在顶部导航选项卡上，你将看到 <strong><strong>Actions</strong></strong> 选项卡。单击它，你可以访问推荐的工作流列表以及创建自己的工作流的选项。</li><li>现在，根据项目的性质，你可以选择从可用列表中选择一个已经创建的工作流，也可以选择自己创建一个。由于你了解项目的全部内容以及可能需要自动化的内容，因此我建议你自己设置一个新的工作流程。这将使你更好地了解正在发生的事情。</li><li>要设置新的工作流程，请单击 <strong><strong>Set up a workflow yourself</strong></strong>（自行设置工作流程）。这将带你进入一个工作流创建界面，其中包含一个名为 <code>main.yml</code> 的新 YAML 文件。既然你选择编写自己的工作流程，在这里，我应该提到了解 YAML 非常重要。</li></ul><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2023/03/actions-tab.png" class="kg-image" alt="actions-tab" width="600" height="400" loading="lazy"></figure><p>在幕后发生的事情是，一旦你单击此选项，就会在 <code>main.yml</code> 文件旁边创建两个文件夹。如果你之后访问你的仓库或查看文件名之前的路径，你将看到：<code>.github/workflows/&lt;filename&gt;</code>。</p><ul><li>在 <code>main.yml</code> 文件中是你定义工作流程的地方，在编写完所有内容后，你可以提交更改（commit the changes），就像对仓库进行更改时所做的那样。这样，你就设置了工作流，它将根据 YAML 文件中定义的触发器运行。</li></ul><p>或者，你仍然可以在你最喜欢的代码编辑器中完成这一切。你需要做的就是将仓库克隆到你的计算机上，在项目的根文件夹中创建一个 <code>.github</code> 文件夹，在其中创建另一个名为 <code>workflows</code> 的文件夹，最后添加一个扩展名为 <code>.yml</code> 的文件并将你的脚本写入这个文件。</p><p>在下面的示例中，我将引用我在项目中实现的代码来帮助你理解。</p><h2 id="github-actions--1">GitHub Actions 组件</h2><p>GitHub Actions 主要由三个主要组件组成，包括：</p><ul><li>工作流（Workflows） - 这些是定义自动化过程的规则集。它们在 YAML 文件中定义，该文件存储在 <code>.github/workflows</code> 目录中。</li><li>事件（Events） - 它们启动工作流。例如，你可以将事件设置为在创建 PR 或新开 issue 时运行工作流。要在工作流中定义事件，请使用关键字 <code>on</code> 后跟事件名称。</li></ul><p>例如：</p><pre><code class="language-yaml">on:
    issues:
        types: [opened]
    pull_request_target:
        types: [opened]
</code></pre><ul><li>任务（Jobs） - 这些构成了工作流程。默认情况下，任务是同时运行的。要在给定的工作流中定义你的任务，请使用关键字 <code>jobs</code>，后跟每个任务及其配置的唯一标识符。</li></ul><p>例如：</p><pre><code class="language-yaml">jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v2
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.10
      - name: Install dependencies
        run: |
          pip install -r requirements.txt
</code></pre><p>所有这些组件确保一组特定的规则被成功执行。现在看看我们的项目。</p><h2 id="-issue-pull-request">如何自动化管理 issue 和 pull request</h2><p>管理 issue 和 pull request 可能是一项非常耗时的工作，尤其是对于大型开源项目。但有了 GitHub Actions，维护者就可以把这些流程自动化，把更多的时间花在编码和与社区互动上。</p><h3 id="-issue-pull-request-">如何创建 issue 和 pull request 模板</h3><p>如果你是一个活跃的开源贡献者，你有可能遇到过一个指南，告诉你在创建 issue 或提交 PR 时应该包括什么。这种模板的主要目的是提供指导，确保贡献者提供所有必要的信息。</p><p>现在，让我们看看你如何在你的项目中创建这个模板：</p><ul><li>第一步是确保在仓库的 root 中有一个 <code>.github</code> 目录，如果你还没有的话。</li><li>在 <code>.github</code> 文件夹内，创建两个文件夹 <code>ISSUE_TEMPLATE</code> 和 <code>PULL_REQUEST_TEMPLATE</code>。</li><li>在这两个文件夹中，添加代表你想自动化内容的 markdown 文件：例如，你可以将 <code>feature_request.md</code> 和 <code>issue_report.md</code> 作为 issue 模板，将 <code>pull_request_template.md</code> 作为 PR 模板。</li></ul><p>下面是我在 <code>pull_request_template.md</code> 文件中写的内容，作为参考。这是一个简单的指南，告诉贡献者在提交 pull request 之前应该包括什么。</p><pre><code class="language-markdown">**Related Issue(s):**
Please provide a title for this pull request.

**Description:**
Please provide a brief description of the changes you are proposing.

**Checklist:**

-   [ ] I have read and followed the [contributing guidelines](/CONTRIBUTING.md).
-   [ ] I have included a README file for my project.
-   [ ] I have updated the main README file where necessary.
-   [ ] I have included a requirements.txt file.
-   [ ] I have added tests that prove my changes are effective or that my feature works.
-   [ ] All new and existing tests pass.

**Screenshots**
If applicable, add screenshots to help explain behavior of your code.

**Additional Notes:**
Please provide any additional information about the changes you are proposing.
</code></pre><p>如需更详细的解释，请在<a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates">这里</a>查看 GitHub Action 关于 issue 和 pull request 模板的文档。</p><h3 id="-">欢迎新的贡献者并表彰社区的努力</h3><p>作为一个维护者，与社区打交道是很重要的，因为你有机会与你的朋辈直接互动并获得反馈。但如果你正在运行一个吸引众多贡献者的大型项目，你可能不会经常有机会直接与社区互动。</p><p>在 GitHub Actions 的帮助下，你可以完成其中的一些任务，比如欢迎新的贡献者，认可他们的努力，并为现有的社区成员创造一个积极的氛围。</p><p>如果你正在管理一个小项目，你可能可以直接与社区互动，但仍然利用自动化来完成一些工作。</p><p>例如，这里有一些示例代码，当新的贡献者创建 pull request 或在仓库上创建一个新的 issue 时，我通过这些代码来欢迎他们。在其中，你可以看到我有一条信息，感谢他们的努力，也向他们保证我将尽快审核他们提交的修改。尽管如此，如果需要额外的东西或提出新的想法，我还是会通过对话去跟进。</p><pre><code class="language-yaml">name: Welcome New Contributors

on:
    issues:
        types: [opened]
    pull_request_target:
        types: [opened]

jobs:
    welcome:
        runs-on: ubuntu-latest
        steps:
            - name: Welcome Issue
              if: github.event_name == 'issues'
              uses: actions/github-script@v5
              with:
                  script: |
                      const issue = context.issue;
                      const repo = context.repo;
                      const issueAuthor = context.payload.sender.login;
                      const welcomeMessage = `
                        Hi @${issueAuthor}! :wave:
                        Thank you for creating an issue in our repository! We appreciate your contribution and will get back to you as soon as possible.
                      `;
                      github.rest.issues.createComment({
                        ...repo,
                        issue_number: issue.number,
                        body: welcomeMessage
                      });
            - name: Welcome Pull Request
              if: github.event_name == 'pull_request_target'
              uses: actions/github-script@v5
              with:
                  script: |
                      const pr = context.issue;
                      const repo = context.repo;
                      const prAuthor = context.payload.sender.login;
                      const welcomeMessage = `
                        Hi @${prAuthor}! :wave:
                        Thank you for submitting a pull request! We appreciate your contribution and will review your changes as soon as possible.
                      `;
                      github.rest.issues.createComment({
                        ...repo,
                        issue_number: pr.number,
                        body: welcomeMessage
                      });
</code></pre><p>除了这个简单的工作流程外，如果你正在领导一个更复杂的项目，你可以考虑编写一个更详细的工作流程，能够自动为贡献者分配徽章、标签或自定义标题。</p><p>同样，你也可以选择添加一个工作流，在贡献者的 pull request 被合并或 issue 被关闭时对其表示感谢。你可以查看 <a href="https://docs.github.com/en/actions/managing-issues-and-pull-requests/using-github-actions-for-project-management">GitHub Action 文档</a>，了解详细的指南。</p><h2 id="-qa-">如何实现代码 QA 的自动化</h2><p>对于大多数开发人员来说，编写高质量的代码是非常重要的，特别是如果他们正在创建与消费者有关的应用。虽然一个项目的成功取决于精心编写和测试的代码，但有时审核修改可能会花些时间，甚至会使用户正需要的功能延迟上线。</p><p>在代码自动化工具的帮助下，你可以保持一致的编码风格，并快速和容易地识别潜在的错误，保持你的项目整洁。</p><p>那么，如何用 GitHub Actions 设置持续集成（CI），整合代码 formatting 和 linting 工具，并在项目中使用自动化代码审核服务？</p><p>持续集成（CI）帮助你实现流程自动化，如构建、测试和验证代码更改。就像其他自动化代码一样，CI 代码写在一个 <code>.yml</code> 文件中，存储在 <code>.github/workflows</code> 文件夹中。</p><p>下面是一个 Python 项目 CI 工作流程的例子，它在向仓库的 <code>main</code> 分支 pull request 时运行。它测试 Python 多个版本的代码，安装必要的依赖，并使用 <code>unittest</code> 模块运行测试。</p><pre><code class="language-yaml">name: Python CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.7, 3.8, 3.9, 3.10]

    steps:
    - uses: actions/checkout@v2
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run tests
      run: |
        python -m unittest discover
</code></pre><p>除了上面的代码，如果你想保持代码风格的一致性，你可以整合代码 formatting 和 linting 工具，如 <code>black</code>、<code>isort</code> 或 <code>flake8</code>。为此，你只需要在 <code>requirements.txt</code> 文件中加入这些工具，该文件已经包含在上述代码中。下面的代码块运行这些工具。</p><pre><code class="language-yaml">#...
    # ...
    - name: Run black for code formatting
      run: |
        black --check .
    - name: Run isort for import sorting
      run: |
        isort --check --diff .
    - name: Run flake8 for linting
      run: |
        flake8 .
</code></pre><p>如果它发现任何代码格式问题，CI 构建将失败。要解决这个问题，你必须手动检查日志。请查看这个关于<a href="https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python">构建和测试 Python</a> 的指南，了解更多的例子。</p><p>上面的想法只是你可以在项目中使用的一些自动程序。对于一个更复杂的应用，你可以考虑增加工作流程，用 Sphinx 或 MkDocs 等工具生成文档，自动化依赖性更新，自动化发布管理和项目跟踪，等等。</p><h2 id="-github-actions-">关于构建自定义 GitHub Actions 的提示</h2><p>在 <a href="https://github.com/marketplace?type=actions">GitHub Actions 市场</a>上已经有很多预制的 action。但有时你可能想要或需要定制工作流程以满足你的需求。</p><p>为此，你可以选择 JavaScript 或 Docker 容器，并与社区分享。</p><p>这里有一些可以遵循的最佳做法：</p><ul><li>了解问题 - 就像其他项目一样，在开始构建之前，确保你了解要解决的问题以及你将如何解决它。</li><li>选择正确的技术栈 - 如上所述，可以使用 JavaScript 或 Docker 编写 GitHub Actions。请确保选择最适合你的需求和理解的方式。</li><li>确保你遵守最佳的编码实践，以便别人能够轻松地理解和阅读你的代码。</li><li>利用已有的软件包，如 <code>@actions/core</code> 和 <code>@actions/github</code>，它们提供了与 GitHub Actions 环境和 GitHub API 的简单互动。</li><li>在成功创建自己的工作流程后，你有可能想要发布它。无论你是否发布，请确保测试你的 action 是否有潜在的问题或错误。</li></ul><p>通过这些简单的技巧，你可以创建一个自定义的 GitHub Action 来自动完成项目中的一些主要/基本任务。除了上面的提示，你可以在<a href="https://docs.github.com/en/actions/creating-actions">官方文档</a>中找到更多关于创建自定义 action 的详细信息。</p><h2 id="--1">总结</h2><p>在本指南中，我们看到了 GitHub Actions 能给我们的项目带来的好处。它不仅简化了生产流程，而且还允许我们自定义 action 以适应项目需要。</p><p>这仅仅是我们能实现的东西的一小部分。我鼓励你更好地理解和探索不同的方法，以进一步用 GitHub Actions 改进你的开源项目。让我们拥抱自动化，利用它来完成更多工作。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 如何在 GitHub 中创建自动的 Pull Request 检查清单 ]]>
                </title>
                <description>
                    <![CDATA[ 原文：How to Create an Automated Pull Request Checklist in GitHub [https://www.freecodecamp.org/news/create-a-pr-checklist-in-github/]，作者： Brittany Joiner [https://www.freecodecamp.org/news/author/brittany/] 如果你曾经为某个项目做过贡献，无论是你的应用程序还是开源工具，你都可能创建了一个 pull request。这要求对你的代码进行更改以合并到主代码库中。 我们使用 pull request 来确保只有高质量的代码被合并到主分支中。但有时我们在经过艰苦的编码开发新功能后会忽略一些小事情，产生错误。 最坏的情况是，这些错误可能会被团队成员忽略，然后合并到主代码库中，导致 bug 或降低效率。而最好的情况是，团队其他成员可能会花些时间来检查出问题并反馈。 我在创建 pull request 的时候特别容易偷懒，所以我做了任何开发人员都会做的事情......我找到了一种自动化生成 p ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/create-a-pr-checklist-in-github/</link>
                <guid isPermaLink="false">62d7841d8d13aa0845c62bdc</guid>
                
                    <category>
                        <![CDATA[ 自动化 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Wed, 27 Jul 2022 06:13:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/07/tarn-nguyen-XlEafYGDvV0-unsplash.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>原文：<a href="https://www.freecodecamp.org/news/create-a-pr-checklist-in-github/">How to Create an Automated Pull Request Checklist in GitHub</a>，作者：<a href="https://www.freecodecamp.org/news/author/brittany/">Brittany Joiner</a></p><p>如果你曾经为某个项目做过贡献，无论是你的应用程序还是开源工具，你都可能创建了一个 pull request。这要求对你的代码进行更改以合并到主代码库中。</p><p>我们使用 pull request 来确保只有高质量的代码被合并到主分支中。但有时我们在经过艰苦的编码开发新功能后会忽略一些小事情，产生错误。</p><p>最坏的情况是，这些错误可能会被团队成员忽略，然后合并到主代码库中，导致 bug 或降低效率。而最好的情况是，团队其他成员可能会花些时间来检查出问题并反馈。</p><p>我在创建 pull request 的时候特别容易偷懒，所以我做了任何开发人员都会做的事情......我找到了一种自动化生成 pull request 检查清单并强迫自己完成工作的方法！</p><p>本教程向你展示如何在浏览器中构建一个扩展，以自动生成一个 pull request 检查清单，在你检查该清单中的每个项目之后，才显示 Create Pull Request（创建拉取请求）这个按钮。</p><h2 id="-">开始</h2><p>在你开始之前，你需要先做准备工作。</p><h3 id="--1">列出要在代码中检查的内容</h3><p>忘记任何工具或任何自动化......花几分钟，想想需要具备什么才是一个好的 pull request，并列出这些项目。</p><p>是什么让你可以轻松查看其他 pull request？或者你经常发现人们评论的常见错误是什么？</p><p>如果你需要一些想法，这是我列出的项目：</p><ul><li>一切按字母顺序排序</li><li>审阅者如何在本地测试代码的说明</li><li>已添加测试</li><li>功能/bug 修复的屏幕截图（如果适用）</li><li>如果添加了任何新文本，则将其国际化</li><li>任何新元素都有 aria 标签</li><li>调试后不会不小心留下 <code>console.logs</code></li><li>我是否为变量和函数使用了简洁明了的名称</li><li>我是否解释了所有可能的解决方案以及为什么选择我所做的那个</li><li>添加注释以使新功能更清晰</li><li>添加了 pull request 标签</li><li>更新任何历史/变更日志文件</li></ul><p>如果你仍然不确定，请与你团队中更高级的开发人员交谈，看看他们在审查 pull requet 时会关注什么。</p><p>创建 PixieBrix 帐户（你的浏览器自动化工具）</p><p>有一些浏览器扩展可以让你创建自动化。我发现 PixieBrix 非常强大，而且它的社区氛围很友好。</p><blockquote>PixieBrix 提供最通用的低代码平台，用于扩展你和你的团队在使用的 Web 应用程序。你将获得你需要的高效的、个性化的体验——来源：<a href="https://www.pixiebrix.com/">PixieBrix</a> 网站</blockquote><p>为了创建我在下面描述的自动化，你需要注册一个免费的 PixieBrix 帐户。</p><p>只需在他们的网站上选择“免费开始”，然后按照引导创建一个帐户。系统将提示你安装 <a href="https://chrome.google.com/webstore/detail/pixiebrix/mpjjildhmpddojocokjkgmlkkkfjnepo">PixieBrix Chrome 扩展程序</a>。</p><p>现在你准备好了！</p><h2 id="-pull-request-">如何构建 pull request 清单自动化</h2><p>好吧，你都准备好了，现在是构建的时候了。</p><p>如果你想采取最直接的路线，你可以激活我已经构建的<a href="https://app.pixiebrix.com/activate?id=@brittany-joiner/gh-on-a-pr">扩展</a>，并随意编辑。</p><p>但是，如果你想从头开始构建它并更熟悉浏览器自动化的工作原理，请按照以下步骤操作。</p><h3 id="-1-pixiebrix-">第 1 步 – 在 PixieBrix 中打开页面编辑器</h3><p>要在 PixieBrix 中构建扩展，你不需要 VSCode 或任何其他编辑器，你可以完全在浏览器中完成所有操作。</p><p>我喜欢首先转到我希望执行操作的页面，在本例中为 <code>github.com</code>。</p><p>要访问编辑器，请右键单击任何网页以打开 Context Menu（上下文菜单）并选择 <code>Inspect</code> 检查。滚动标签（你知道，<em><em><code>Elements</code></em>、<em><code>Console</code></em>、<em><code>Network</code></em> </em>等标签），直到你看到 <code>PixieBrix</code>。</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/07/open-page-editor.gif" class="kg-image" alt="demonstration-of-opening-inspector-and-choosing-pixiebrix-tab" width="600" height="400" loading="lazy"><figcaption>右键单击 Inspect，然后转到 PixieBrix 选项卡</figcaption></figure><p>系统可能会提示你允许某些权限，但随后你会发现一个空白页面，左上角有一个按钮，上面写着 “Add（添加）”，这就是我们要开始的地方。</p><h3 id="-2-">第 2 步 - 添加触发</h3><p>要在 PixieBrix 中构建扩展，你需要将积木链在一起。你可以将砖块视为功能，扩展是主要功能，按你配置的顺序执行较小的功能。</p><p>你有多种选择来触发此扩展。</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-2.33.29-PM.png" class="kg-image" alt="pixiebrix-trigger-options-menu" width="600" height="400" loading="lazy"><figcaption>PixieBrix 中的扩展触发器选项</figcaption></figure><p>你可以选择手动操作，例如向页面添加按钮或 context menu（当你右键单击网页时 - 与你进入检查器的菜单相同），或者你可以使用快速栏命令（键盘快捷键）。</p><p>侧边栏面板会在浏览器右侧打开一个面板，它实际上不是触发器，而是用于为另一个触发器创建显示。</p><p>对于这个工作流程，请使用 <code>Trigger</code> 选项。该选项会在你加载特定网页并满足你配置的其他条件时运行扩展程序。</p><p>这是它的界面：</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-2.51.09-PM.png" class="kg-image" alt="Screen-Shot-2022-07-10-at-2.51.09-PM" width="600" height="400" loading="lazy"></figure><p>你可以将顶部的名称更改为你喜欢的名称，例如 <code>Github PR Checklist</code>。</p><p>要配置触发器，请考虑何时要查看检查清单。你可以设置一访问 GitHub 就启动它，但这可能比你想要的更频繁，因为当你阅读 issue 或在 repo 中搜索某些内容时不需要清单。</p><p>我决定在页面上有一个 <code>create pull request</code> 按钮元素时触发它，这表明我即将打开一个拉取请求，所以这可能是检查我的清单的好时机！</p><p>因此，请创建一个 pull request 并导航到具有该绿色按钮的页面（同时保持页面编辑器打开）。</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-5.12.04-PM.png" class="kg-image" alt="github-create-pull-request-button" width="600" height="400" loading="lazy"><figcaption>GitHub 上的创建 pull request 按钮</figcaption></figure><p>看到该按钮后，滚动到触发器的 <code>Advanced: Match Rules</code> 部分，然后查找 <code>Selectors</code> 字段。</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-5.13.46-PM.png" class="kg-image" alt="selector-field-in-pixiebrix-trigger-brick" width="600" height="400" loading="lazy"><figcaption>PixieBrix 触发配置中的 Selector 部分</figcaption></figure><p>你可以使用鼠标打开元素选择器视图并单击以选择按钮，或者你可以直接在字段中复制此类。</p><pre><code>.hx_create-pr-button
</code></pre><p>现在你已经创建了一个触发器，该触发器表示你可以随时加载托管在 <code>github.com</code> 上的页面。</p><p>好的，所以我们已经确定了该按钮的类，所以最难的部分已经完成了！现在我们只需要隐藏它，显示清单，然后在清单完成后再次显示它。</p><h3 id="-3-create-pull-request-">第 3 步 – 隐藏 <code>create pull request</code> 按钮</h3><p>选择触发器下方的加号按钮以添加另一个部分。你将看到一个开放的市场，允许你搜索所有可用的块。搜索 <code>hide</code>，你会看到这个部分。</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-5.16.07-PM.png" class="kg-image" alt="pixiebrix-marketplace-with-hide-brick" width="600" height="400" loading="lazy"></figure><p>将鼠标悬停在 “Hide” 块上并查看更多选项，然后选择 “Add” 将其添加到你的扩展程序中。</p><p>这个部分需要的唯一配置是隐藏哪个元素。在这个示例中，它将与我们在触发器中使用的元素完全相同——创建拉取请求按钮。因此，你可以复制同一个类并将其设置为选择器的值。</p><h3 id="-4-">第 4 步 – 打开侧边栏</h3><p>添加另一个名为 <code>Show Sidebar</code> 的部分。这将在浏览器右侧打开一个面板以显示内容。</p><p>我将 <code>panelHeading</code> 字段设置为 <code>PR</code>，以指定它应该加载 <code>PR</code> 选项卡。如果你尚未设置其他侧面板，则无需在此处放置任何东西，你可以跳到下一步。</p><h3 id="-5-issue-">第 5 步 - 把 issue 分配给自己</h3><p>在我们进入清单之前，除了显示清单和隐藏按钮之外，我还添加了一项自动化功能。</p><p>我创建了一个动作来把 issue 分配给自己。这只是一个点击，但为什么不让机器人去做呢？😊</p><p>请添加另一个名为 <code>Simulate a DOM event</code> 的部分。这就像它听起来的那样......它假装对特定元素做某事，例如点击它。</p><p>为你希望与之交互的元素和事件提供选择器。</p><p>就像在触发器和隐藏部分中一样，你可以使用鼠标按钮在屏幕上打开选择器，然后选择 <code>assign yourself</code> 链接以自动将这些类应用到选择器字段。</p><p>你还可以通过将其复制并粘贴到 <code>selector</code> 字段中来手动应用该类：</p><pre><code>#new_pull_request .js-issue-assign-self
</code></pre><p>确保为 <code>event</code> 选择 <code>click</code>，一切就绪！</p><h3 id="-6-">第 6 步 - 创建你的清单</h3><p>现在我们正处于扩展的核心。是时候建立清单了。选择加号按钮并添加 <code>Show a modal or sidebar form</code> 部分。</p><p>这是用于设计表单，对于我们在提交拉取请求之前要确认或考虑的每个项目，将是一个复选框字段。</p><p><strong>设置表单标题和描述</strong></p><p>这些纯粹是装饰性的，因此请将它们设置为你想要的任何内容。</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-3.09.11-PM-1.png" class="kg-image" alt="form-settings-for-pixiebrix-form-brick" width="600" height="400" loading="lazy"></figure><h4 id="--2"><strong>配置你的第一个字段</strong></h4><p>在打开拉取请求之前获取你要查看的项目列表，然后选择第一个。这将是我们的第一个表单字段，你需要在 PixieBrix 中设置以下字段：</p><ul><li><code>name</code></li><li><code>label</code></li><li><code>input type</code></li></ul><p>名称和标签可以是任何你想要的。<strong>保持名称简单</strong>，因为你需要在下一步检查它是否正确时引用它。<strong>标签是复选框旁边的视觉显示</strong>。对于输入类型，选择<strong>复选框</strong>。</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-5.29.30-PM.png" class="kg-image" alt="pixiebrix-form-field-configured" width="600" height="400" loading="lazy"><figcaption>PixieBrix form 字段配置</figcaption></figure><p>你可以在 PixieBrix 页面编辑器的右侧面板上预览它的外观。</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-5.30.21-PM.png" class="kg-image" alt="previewed-form-in-pixiebrix" width="600" height="400" loading="lazy"></figure><h4 id="--3">将其余项目添加为新字段</h4><p>在字段上方滚动以选择显示“添加新字段”的蓝色按钮，然后为你有的项目再次执行所有操作。</p><h4 id="--4">最终表单配置</h4><p>快完成了！在表单字段选项下方滚动，直到看到 <code>Submit Button Text</code>。你可以保持原样，但我将我的自定义为 <code>Ready to Open</code> 以使按钮操作更加清晰。</p><p>最重要的是，通过选择下拉菜单将 <code>Location</code> 值更改为 <code>sidebar</code> 而不是 <code>modal</code>。这会将表单设置为显示在我们在上一步中打开的侧栏中。</p><h3 id="-7-create-pull-request-">第 7 步 – 完成清单后显示 <strong><code>create pull request</code></strong> 按钮</h3><p>向这个名为 <code>Show</code> 的扩展添加最后一部分。这类似于 Hide，我们将把我们一直引用的同一类传递给 <code>create pull request</code> 按钮。</p><p>如果你需要复习，请看这里：</p><pre><code>.hx_create-pr-button
</code></pre><p>还有一个要配置的部分。我们想控制这个部分何时执行，因为我们只想在表单提交中检查每个项目时显示按钮。</p><p>我们可以将表单中的每个字段都设置为必填项，这样在检查完所有内容之前你无法提交表单。但另一种方法是编辑此部分的高级选项下的 <code>Condition</code> 字段。</p><p>你可以在此处指定此特定部分何时运行。如果清单中的每个字段都为真，你将构建一个返回真的语句。</p><p>这就是语法的样子，你需要将 <code>item</code> 值换成每个项目的名称。</p><pre><code>{{ "true" if @form.item1 and @form.item2 and @form.item3 and @form.item4 and @form.item5 and @form.item6 and @form.item7 and @form.item8 and @form.item9 and @form.item10 and@form.item11 }}
</code></pre><p>完成后，你的设置应如下所示：</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2022/07/Screen-Shot-2022-07-10-at-5.35.44-PM.png" class="kg-image" alt="show-brick-configuration" width="600" height="400" loading="lazy"></figure><p>选择 PixieBrix 页面编辑器右上角的蓝色保存按钮以保存你的扩展程序。</p><h2 id="--5">试一试</h2><p>现在试一试！无论你是激活了预构建的扩展，还是按照教程自行构建，你都已准备好进行测试。</p><p>打开一个 pull request，你将看到侧边栏表单并且没有绿色按钮。检查列表中的所有项目，然后提交，然后突然出现你的按钮，你已经被分配到 PR！</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/07/demo-pr-checklist.gif" class="kg-image" alt="demo-of-pr-checklist" width="600" height="400" loading="lazy"><figcaption>PR 检查清单的 demo</figcaption></figure><p>如果你在开始构建它时遇到任何问题，或者它没有按预期工作，PixieBrix 社区很活跃，维护者总是愿意加入并提供帮助。</p><p>但是，如果你是一个视觉学习者并且更喜欢观看，我制作了一个<a href="https://youtu.be/cpZ1J2s-2jk">视频</a>，向你展示如何构建这个自动化 PR 检查清单。</p><p>感谢你阅读本文！</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 如何编写一个脚本，每天改变你的 ZOOM 的背景 ]]>
                </title>
                <description>
                    <![CDATA[ 原文：How to Write a Script to Change Your Zoom Background Every Day [https://www.freecodecamp.org/news/how-to-write-a-script-to-change-zoom-background/] ，作者：Saransh Kataria [https://www.freecodecamp.org/news/author/saransh-kataria/] 在过去的几个月里，我为我在徒步旅行时拍摄的照片找到了新的用途。我开始用它们作为 ZOOM 的虚拟背景。 如果你和我一样，拍了很多照片，可能很难决定哪一张看起来不错。然后我决定把它们都用上，在不同的日子里用不同的照片。 遗憾的是，ZOOM 没有这个内置功能。因此，作为一个软件开发者，我不得不把每天随机选择一个 ZOOM 虚拟背景的过程自动化。 脚本是怎么做的？ ZOOM 确实有一个 API，我可以用它来每天改变我的背景——但这项任务似乎太费劲了。软件开发者生来就很懒，对吧？:) 然而，我发现 ZOOM 应用程序会在其 pre ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-to-write-a-script-to-change-zoom-background/</link>
                <guid isPermaLink="false">625f8a4e99ec7406219e6fba</guid>
                
                    <category>
                        <![CDATA[ 自动化 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Tue, 19 Apr 2022 12:20:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/04/zoom-background-article-image.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>原文：<a href="https://www.freecodecamp.org/news/how-to-write-a-script-to-change-zoom-background/">How to Write a Script to Change Your Zoom Background Every Day</a>，作者：<a href="https://www.freecodecamp.org/news/author/saransh-kataria/">Saransh Kataria</a></p><p>在过去的几个月里，我为我在徒步旅行时拍摄的照片找到了新的用途。我开始用它们作为 ZOOM 的虚拟背景。</p><p>如果你和我一样，拍了很多照片，可能很难决定哪一张看起来不错。然后我决定把它们都用上，在不同的日子里用不同的照片。</p><p>遗憾的是，ZOOM 没有这个内置功能。因此，作为一个软件开发者，我不得不把每天随机选择一个 ZOOM 虚拟背景的过程自动化。</p><h2 id="-">脚本是怎么做的？</h2><p>ZOOM 确实有一个 API，我可以用它来每天改变我的背景——但这项任务似乎太费劲了。软件开发者生来就很懒，对吧？:)</p><p>然而，我发现 ZOOM 应用程序会在其 preferences（偏好）文件夹中创建一个被选中的背景副本，并引用它。脚本只是随机抽取一个文件，然后用这个背景文件替换它。然后呢？一个不同的 ZOOM 虚拟背景就显示出来了。</p><p>然后你可以把它作为 cron job，每天执行（或任何你喜欢的频率），定期改变背景。</p><h2 id="--1">设置</h2><p>我把所有我想用作背景的图片放在我的用户目录的一个文件夹里。我的是 <code>/zoom/bgpictures/</code>，这就是我在脚本中使用的。但这是一个变量，你可以把它改成你想要的样子。</p><p>接下来，我们在应用程序中设置一个 ZOOM 虚拟背景。你选择哪个背景并不重要。我们所需要的是 ZOOM 将分配给这个背景的唯一 ID。</p><p>目录中可能已经有一些文件，但我们要选择刚刚上传的图片相对应的文件，以避免替换不同的文件。</p><p>目录是：<code>~/Library/Application Support/zoom.us/data/VirtualBkgnd_Custom</code>. 文件名像这样：<code>9WAE197F-90G2-4EL2-9M1F-AP784B4C2FAD</code></p><h1 id="--2">如何编写脚本</h1><p>我们将使用一个 bash 脚本来替换我们刚才使用的图片。我将把这个脚本放在我为背景图片创建的 ZOOM 文件夹中。同样，它可以被命名为你喜欢的任何名字——我的名字是 <code>~/zoom/zoombg.sh</code>。</p><p>脚本的内容如下：</p><pre><code class="language-bash">#!/bin/bash
# The name of file that we copied before and will be replaced with
OG_BG="9WAE197F-90G2-4EL2-9M1F-AP784B4C2FAD";

# Directory where Zoom keeps the backgrounds
ZOOM_DIR="/Users/$USER/Library/Application Support/zoom.us/data/VirtualBkgnd_Custom/";

# Directory of our images
BGPATH="/Users/$USER/zoom/bgpictures/";

# Picking a random file
NEW_BG=$(find "$BGPATH" -type f | sort -R | head -1);

# Replacing the file
cp -R "$NEW_BG" "$ZOOM_DIR/$OG_BG";</code></pre><p>如果你为目录选择了不同的路径，只要确保在变量中进行修改即可。我们需要通过运行命令使这个脚本可执行：</p><pre><code class="language-bash">chmod 755 ~/zoom/zoombg.sh</code></pre><h1 id="-zoom-">如何随机地改变你的 ZOOM 背景</h1><p>这个脚本已经准备好了。我们需要做的是把它放在一个 cron job 中，这是一个内置的基于时间的工作调度器。我们需要决定改变 ZOOM 虚拟背景的频率的时间表。我在每天上午 9:55 做，因为我的会议在上午 10 点开始。</p><p>如果你是 cron job 的新手，你可以使用<a href="https://corntab.com/">生成器</a>来帮助你。我使用的是：</p><pre><code class="language-bash">55 9 * * 1-5 /Users/saranshkataria/zoom/zoombg.sh &gt; /dev/null 2&gt;&amp;1</code></pre><p>第一部分（55 9 * * 1-5）是你需要根据你的时间表进行定制的。第二部分只是告诉操作系统在那个时间点上要做什么。如果你为 bash 脚本选择了不同的位置，你就需要更新路径。</p><p>要把它放在一个 cron job 中，键入：</p><pre><code class="language-bash">crontab -e</code></pre><p>它将打开一个编辑器。按键盘上的 I 键进入插入模式，粘贴这一行，然后按 Escape 键，再按 “:wq” 和回车键，保存并退出。</p><p>这就是它的全部内容了！现在你每天都会有一个随机的 ZOOM 虚拟背景（或你选择的任何频率）。</p><p>如果你使用的是 Windows，你可以对脚本进行相应的修改。</p><p>如果你有任何问题，请随时与我联系。</p><p><em><em><em><em>欢迎在 </em></em></em></em><a href="https://www.wisdomgeek.com/"><em><em><em><em>https://www.wisdomgeek.com</em></em></em></em></a><em> 阅读我的更多文章。</em></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 如何用 Husky 向 Git 添加 Commit Hooks 以实现代码任务的自动化 ]]>
                </title>
                <description>
                    <![CDATA[ 原文：How to Add Commit Hooks to Git with Husky to Automate Code Tasks [https://www.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/] ，作者：Colby Fayock [https://www.freecodecamp.org/news/author/colbyfayock/] 有很多工具可以使我们的代码任务自动化。我们可以用ESLint检查语法问题，用Prettier格式化代码。 但并不是团队中的每个人都会记得每次提交时都要运行这些命令。我们如何使用Husky来添加Git钩子来为我们运行这些命令？  * 什么是 Git Hooks? [./#what-are-git-hooks]  * 什么是 Husky? [./#what-is-husky]  * 我们要构建什么？ [./#what-are-we-going-to-build]  * 第0步：建立一个新的项目 [./#st ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/</link>
                <guid isPermaLink="false">624bc83299ec7406219e5736</guid>
                
                    <category>
                        <![CDATA[ 自动化 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ luojiyin ]]>
                </dc:creator>
                <pubDate>Tue, 05 Apr 2022 04:47:55 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/04/husky.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>原文：<a href="https://www.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/">How to Add Commit Hooks to Git with Husky to Automate Code Tasks</a>，作者：<a href="https://www.freecodecamp.org/news/author/colbyfayock/">Colby Fayock</a></p><!--kg-card-begin: markdown--><p>有很多工具可以使我们的代码任务自动化。我们可以用ESLint检查语法问题，用Prettier格式化代码。</p>
<p>但并不是团队中的每个人都会记得每次提交时都要运行这些命令。我们如何使用Husky来添加Git钩子来为我们运行这些命令？</p>
<ul>
<li><a href="https://chinese.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/#what-are-git-hooks">什么是 Git Hooks?</a></li>
<li><a href="https://chinese.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/#what-is-husky">什么是 Husky?</a></li>
<li><a href="https://chinese.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/#what-are-we-going-to-build">我们要构建什么？</a></li>
<li><a href="https://chinese.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/#step-0-setting-up-a-new-project">第0步：建立一个新的项目</a></li>
<li><a href="https://chinese.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/#step-1-installing-husky-to-a-project">第1步：将 Husky 安装到一个项目上</a></li>
<li><a href="https://chinese.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/#step-2-configuring-husky-to-run-git-hooks">第2步：配置Husky以运行Git钩子</a></li>
<li><a href="https://chinese.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/#step-3-using-husky-to-format-code-with-prettier">第3步：使用Husky用Prettier格式化代码</a></li>
</ul>
<h2 id="what-are-git-hooks?>什么是 Git Hooks？</h2>
<p><a href=" https:="" git-scm.com="" docs="" githooks"="">Git hooks 是你可以设置的脚本，以便在Git生命周期中 <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">在某些事件中运行</a>。这些事件包括提交的不同阶段，如提交前（pre-commit）和提交后（post-commit）。<p></p>
<p>这些都很有用，因为它们允许开发者运行自定义的代码任务，甚至通过自动化其他脚本来执行这些任务来执行标准。</p>
</h2><h2 id="what-is-husky?">什么是 Husky？</h2>
<p><a href="https://github.com/typicode/husky">Husky</a>是一个工具，它允许我们轻松地处理Git Hooks 并在提交代码时运行我们想要的脚本。</p>
<blockquote>
<p>它的工作原理是在我们的 <code>package.json</code> 文件中加入一个对象，配置 Husky 来运行我们指定的脚本。之后，Husky会管理我们的脚本将在Git生命周期的哪个阶段运行。</p>
</blockquote>
<h2 id="what-are-we-going-to-build?">我们要构建什么？</h2>
<p>我们将建立一个简单的项目，用来测试Git Hooks。</p>
<p>虽然你应该能够跟上你正在使用的任何项目，但我将使用 <a href="https://nextjs.org/">Next.js</a> 作为这个项目的起点，只是因为我们可以运行一个命令来启动项目。</p>
<p>关于这个项目，有一点需要注意的是，我们将使用 <a href="https://prettier.io/">Prettier</a> 作为例子，说明你可以用 Git Hooks 做什么。</p>
<p>Prettier 是一个会自动为我们格式化代码的工具，如果你不期望它发生，就会造成很大的压力。跟随我使用 Next.js 项目，可以让你在不做任何无意改动的情况下测试一下。</p>
<p>至于测试Git Hooks，我们将从添加一个简单的命令行语句开始，看看 Husky 的工作。但我们还将测试添加Prettier，它将自动为我们格式化我们的代码。</p>
<p>最后，在写这篇文章的时候，Husky 发布了一个 <a href="https://typicode.github.io/husky/#/">v5 Alpha</a> 版本的Git Hooks 解决方案。鉴于它还只是一个Alpha版本，我们将继续使用<a href="https://github.com/typicode/husky/tree/v4.3.0">v4</a>，它允许我们用npm轻松安装 Husky 。</p>
<h2 id="step-0-setting-up-a-new-project">第0步：建立一个新的项目</h2>
<p>正如我所提到的，你可以按照同样的步骤来处理任何用<code>package.json</code>文件管理的项目。</p>
<p>Next.js对于本攻略来说绝对是多余的，但我们的目标是尽量减少实际使用Husky时的设置步骤。</p>
<p>要开始使用Next.js，请进入到你想启动项目的目录，并运行以下程序：</p>
<pre><code class="language-shell">yarn create next-app my-husky-project
# or
npx create-next-app my-husky-project
</code></pre>
<p><em>注意：请随意将<code>my-husky-project</code>替换为你想命名的目录。</em></p>
<p>这将创建一个新的文件夹，创建一个新的Next.js项目，并安装所有的依赖项。</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/create-next-app.jpg" alt="create-next-app" width="600" height="400" loading="lazy"></p>
<p>一旦完成，进入到那个新的文件夹，我们就应该准备好了。</p>
<p><a href="https://github.com/colbyfayock/my-husky-project/commit/9e0b39c8f34c2755e074a32ef9de8d4047b68f67">Follow along with the commit</a>.</p>
<h2 id="step-1-installing-husky-to-a-project">第1步：将 Husky 安装到一个项目上</h2>
<p>要安装Husky，我们可以使用 yarn 或 npm。</p>
<pre><code class="language-shell">yarn add husky
# or
npm install husky
</code></pre>
<p><em>注意：如果此时安装 Husky 会安装v5 版，这意味着v5已经正式发布。请参阅 <a href="https://typicode.github.io/husky/#/">更新 Husky 文档</a>，或者你可以在安装时指定husky@4.3.0（或任何最新的版本）来安装最新的v4版本。</em></p>
<p>一旦软件包安装完毕，我们就应该准备好使用 Husky。</p>
<p><a href="https://github.com/colbyfayock/my-husky-project/commit/720728cd595d41c9197640bd4c48e9133bd7d956">伴随着提交的过程</a>.</p>
<h2 id="step-2-configuring-husky-to-run-git-hooks">第2步：配置Husky以运行Git钩子</h2>
<p>接下来，我们要设置Husky，这样我们就可以使用它作为我们的Git hooks。</p>
<p>在我们的<code>package.json</code>文件中，创建一个名为<code>husky</code>的新属性，并设置一个空对象。</p>
<pre><code class="language-json">"husky": {},
</code></pre>
<p>你可以在 <code>package.json</code> 文件中的任何地方添加这个属性，但我要把它添加到 <code>scripts</code> 属性的下面，这样我可以更容易地把它们放在一起管理。</p>
<p>在这里面，我们要添加另一个叫做 <code>hooks</code> 的属性，它也指定了一个空对象：</p>
<pre><code class="language-json">"husky": {
  "hooks": {}
},
</code></pre>
<p>这就是我们要添加Git hooks 的地方。Husky 几乎支持<a href="https://git-scm.com/docs/githooks">Git定义的所有Git钩子</a>，所以我们可以在Git事件流程中尽可能灵活地使用。</p>
<p>为了测试这一点，我创建了 <a href="https://github.com/colbyfayock/my-husky-project/tree/main+test">一个新的分支</a>，在那里我添加了该页面上的所有Git hooks，包括一个简单地写入终端 <code>[Husky] 事件名称</code> 的脚本。</p>
<p><em>注意：不要觉得你需要这样做，除非你很好奇。我们的目标是通过我的例子向你展示它是如何工作的。</em></p>
<pre><code class="language-json">"husky": {
  "hooks": {
    "applypatch-msg": "echo \"[Husky] applypatch-msg\"",
    "pre-applypatch": "echo \"[Husky] pre-applypatch\"",
    "post-applypatch": "echo \"[Husky] post-applypatch\"",
    "pre-commit": "echo \"[Husky] pre-commit\"",
</code></pre>
<p>这样做的目的是告诉Husky，在每一个Git hooks 的阶段，都要告诉我们！</p>
<p>当我提交这个改动时，我们可以立即看到 Husky 启动了我们的一些脚本。</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/husky-commit-hooks.jpg" alt="husky-commit-hooks" width="600" height="400" loading="lazy"></p>
<p>这些都是Git允许我们在提交过程中钩住的所有事件。</p>
<p>同样，如果我把这些改动推送到Github，我可以看到推送过程中运行了<code>pre-push</code> hook!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/husky-push-hooks.jpg" alt="husky-push-hooks" width="600" height="400" loading="lazy"></p>
<p>你可能永远不会用到 Husky 和 Git 提供的大部分 hooks（我们在这两个命令之间只看到了几个）。</p>
<p>但能够看到这一点是非常棒的，无论是运行格式化我们的代码、防止秘密访问密钥被提交的代码，还是其他真正能够帮助你的工作流程自动化的重要任务。</p>
<p>我们现在可以看到，我们可以通过在<code>package.json</code>中指定配置和挂钩来配置Husky。</p>
<p><a href="https://github.com/colbyfayock/my-husky-project/commit/108583a7e96564baf0fac994eafa6cf98d65d03e">Follow along with the commit</a>.</p>
<p><em>注意：如果你想查看我的分支，其中包括每一个用于测试的Git挂钩，<a href="https://github.com/colbyfayock/my-husky-project/tree/main+test">你可以在Github上找到它</a>。</em></p>
<h2 id="step-3-using-husky-to-format-code-with-prettier">第3步：使用Husky用Prettier格式化代码</h2>
<p>最后，对于一个真实世界的用例，我们要测试一下使用Prettier来自动格式化我们的代码。</p>
<p>Prettier是一个有固定风格的代码格式化工具，它允许你轻松地清理你的代码，使它看起来像一个人写的。</p>
<p>为什么像Prettier这样的工具很重要？当通过代码工作时，特别是与一个团队一起工作时，保持一致性是很重要的，这样每个人都知道应该期待什么。这将有助于防止在代码审查中为一个分号争论不休，但也有助于发现语法错误和防止错误。</p>
<p><em>警告：运行 Prettier 会自动格式化你所有的代码。虽然我们要在提交修改前进行测试，但一旦你把它作为Git Hook应用，它就会自动完成这个过程。</em></p>
<p>为了开始使用 Prettier，让我们用软件包管理器安装它：</p>
<pre><code class="language-shell">yarn add prettier -D
# or
npm install prettier --save-dev
</code></pre>
<p>注意：我们将Prettier作为一个 <code>devDependency</code> 来安装，因为我们的应用程序不需要它来运行。</p>
<p>接下来，我们可以在我们的 <code>package.json</code> 中添加一个新的脚本，这将使我们更容易运行Prettier来进行测试。</p>
<p>在<code>scripts</code>属性里面，添加：</p>
<pre><code class="language-json">"lint": "prettier --check ."
</code></pre>
<p>对于这第一个测试，我们将以“检查”的方式运行，这将允许我们看到哪些文件会发生变化。</p>
<p>运行以下内容：</p>
<pre><code class="language-shell">yarn lint
# or 
npm run lint
</code></pre>
<p>而一旦我们这样做，我们可以看到，Prettier告诉我们，会改变列出的文件。</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/prettier-check.jpg" alt="prettier-check" width="600" height="400" loading="lazy"></p>
<p>在这一点上，我们的代码将保持不变。但如果我们想真正运行Prettier来进行这些修改，我们可以先添加一个额外的脚本:</p>
<pre><code class="language-json">"format": "prettier --write ."
</code></pre>
<p>而如果我们运行该脚本，它将更新所有这些文件，使代码的格式符合Prettier的规范。</p>
<p>_警告：只是另一个注意，运行Prettier来写修改，将在你的文件中进行修改。这些都是代码风格的改变，不应该影响代码的运行，而是影响代码的外观。在运行格式之前，你应该用Git提交来保存任何修改，这样你就可以在不满意的情况下轻松地恢复这些修改。</p>
<p>现在你可以用以下方式运行脚本：</p>
<pre><code class="language-shell">yarn format
</code></pre>
<p>而我们可以看到，Prettier 更新了我们的文件！</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/prettier-write.jpg" alt="prettier-write" width="600" height="400" loading="lazy"></p>
<p>现在是与本攻略相关的部分：我们可以把它作为一个Git hook加入。这样，当有人试图提交代码时，Prettier 会在代码被保存之前运行。这意味着我们将始终保持代码与Prettier的格式化风格一致。</p>
<p>在我们的Husky hook 配置里面，让我们添加：</p>
<pre><code class="language-json">"husky": {
  "hooks": {
    "pre-commit": "prettier --write . &amp;&amp; git add -A ."
  }
},
</code></pre>
<p>如果你注意到在我们的预提交 hook，我们也加入了<code>git add -A .</code>。</p>
<p>当Husky运行时，它只是运行提供的脚本。当运行我们的 Prettier 命令时，我们只是对代码进行格式化，但我们从未将这些修改作为过程的一部分来保存。所以我们使用<code>git add</code>来存储所有这些修改，并将其纳入提交。</p>
<p>To test this out, I reverted the changes to all of the files that were formatted before. If you’re following along with the same project, you can run:<br>
为了测试这一点，我将恢复对之前进行过格式化的文件的更改。如果你在跟着创建这个项目，你可以运行：</p>
<pre><code class="language-shell">git checkout pages
</code></pre>
<p>这将重置 <code>pages</code> 中的所有修改，使之成为最后一次提交。</p>
<p>现在，让我们试着用Git添加所有的文件并提交修改。</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/git-commit-husky-precommit-prettier.jpg" alt="git-commit-husky-precommit-prettier" width="600" height="400" loading="lazy"></p>
<p>一旦我们运行提交命令，我们可以看到 Husky 的预提交 hook 已经启动，并且格式化了我们的代码。</p>
<p><a href="https://github.com/colbyfayock/my-husky-project/commit/315112d062a791f20eda11f9c608c5fa794ba73e">跟随提交</a>.</p>
<h2 id="">我接下来能做什么？</h2>
<h3 id="linetstaged">使用linet-staged，只对更改过的文件运行格式化。</h3>
<p>我们在预提交 hook 中使用Prettier，并指定<code>.</code>，这意味着它每次都会在所有文件上运行。</p>
<p>我们可以使用一个叫做<a href="https://github.com/okonet/lint-staged">lint-staged</a>的工具，它允许我们仍然用Husky来运行我们的Git钩子，但它只会运行在已经提交的文件上。</p>
<p>例如，如果我们想用Husky和Prettier来做这件事，我们的配置：</p>
<pre><code class="language-json">"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*": "prettier --write"
},
</code></pre>
<p>作为 <code>lint-staged</code> 运行方式的一部分，它将自动为我们把更改的文件附加到我们的 Prettier 语句的末尾。</p>
<p>你也会注意到我们没有包括<code>git add</code>，lint-staged也会为我们自动添加任何变化到Git上。</p>
<h3 id="prettier">设置一个Prettier配置来定制格式化规则</h3>
<p>Prettier 是非常固定风格的 。有一些东西我个人并不喜欢，你可能也有同样的感觉。</p>
<p>幸运的是，Prettier允许你设置一个配置文件，可以覆盖其中的一些文件，使你的代码只是你和你的团队想要的方式。</p>
<h3 id="prettierprettierignore">告诉Prettier用.prettierignore来忽略文件</h3>
<p>你也可能不希望Prettier运行在 <strong>所有的东西</strong> 上（也许你想）。</p>
<p>Prettier允许你在项目根目录下的<code>package.json</code>旁边设置一个<code>.prettierignore</code>文件，类似于<code>.gitignore</code>，它允许你告诉Prettier不应该处理哪些文件。</p>
<p><a href="https://twitter.com/colbyfayock"><img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="600" height="400" loading="lazy"></a></p>
<ul>
<li><a href="https://twitter.com/colbyfayock">在Twitter 关注我</a></li>
<li><a href="https://youtube.com/colbyfayock">订阅我的 Youtube 频道</a></li>
<li><a href="https://www.colbyfayock.com/newsletter/">✉️ 注册订阅我的 Newsletter</a></li>
<li><a href="https://github.com/sponsors/colbyfayock">赞助我</a></li>
</ul>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Python 基础教程：这个自动化程序让你的工作更高效 ]]>
                </title>
                <description>
                    <![CDATA[ 很多日常工作可以通过自动化的方式来帮你节省一点宝贵的时间。这也使得掌握自动化技术成为关键。 只需要一小部分熟练的自动化工程师和领域专家就有可能将整个团队中的最繁琐的工作实现自动化。 在这篇文章中，我们将探讨基于 Python（一种强大的且简单易学的编程语言）来实现自动化工作流程的一些基础知识。我们将使用 Python 来编写一个简单有用的小型自动化脚本，这个脚本能够整理指定文件夹中的文件，并将其放到对应的文件夹中。 我们的目标不是在一开始就编写完美的代码以及构建一套理想的自动化体系。 当然我们也不会创建任何“非法”的脚本。相反的，我们将研究如何创建一个能够自动整理文件夹内容的脚本。 目录  1. 自动化的领域 * 简单的自动化      * 公共 API（Application Program Interface 应用程序接口）的自动化      * API 的逆向工程            2. 自动化的道德考量  3. 创建整理文件夹脚本  ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/building-bots-in-python/</link>
                <guid isPermaLink="false">5fe4701a39641a0517d525dd</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 自动化 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 机器人 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jiawei Pan ]]>
                </dc:creator>
                <pubDate>Wed, 05 May 2021 09:00:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2020/12/freecodecamp_cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>很多日常工作可以通过自动化的方式来帮你节省一点宝贵的时间。这也使得掌握自动化技术成为关键。</p>
<p>只需要一小部分熟练的自动化工程师和领域专家就有可能将整个团队中的最繁琐的工作实现自动化。</p>
<p>在这篇文章中，我们将探讨基于 Python（一种强大的且简单易学的编程语言）来实现自动化工作流程的一些基础知识。我们将使用 Python 来编写一个简单有用的小型自动化脚本，这个脚本能够整理指定文件夹中的文件，并将其放到对应的文件夹中。</p>
<p>我们的目标不是在一开始就编写完美的代码以及构建一套理想的自动化体系。</p>
<p>当然我们也不会创建任何“非法”的脚本。相反的，我们将研究如何创建一个能够自动整理文件夹内容的脚本。</p>
<h1 id="">目录</h1>
<ol>
<li>自动化的领域
<ul>
<li>简单的自动化</li>
<li>公共 API（Application Program Interface 应用程序接口）的自动化</li>
<li>API 的逆向工程</li>
</ul>
</li>
<li>自动化的道德考量</li>
<li>创建整理文件夹脚本</li>
<li>一份自动化程序的完整指南</li>
</ol>
<h2 id="">自动化的领域</h2>
<p>让我们从定义哪种类型的自动化开始。</p>
<p>自动化技术适用于大多数领域。从初级的，它可以帮你从一堆文档中提取邮箱地址，这样你就可以群发邮件了。到复杂一点的，优化大型公司的内部工作流程。</p>
<p>当然，从小型的个人脚本到可以替代人工的大型自动化系统，这中间需要一个学习的过程。所以让我们来看看你适合从哪个领域开始自动化之旅。</p>
<h3 id="">简单的自动化</h3>
<p>直接针对工作中的某一点流程实现简单的自动化。这其中可以是某些小型的独立的步骤，例如整理项目并重新编排目录中的文件，也可以是整个工作流程中一部分，例如自动调整已经保存文件的大小。</p>
<h3 id="api">公共 API 的自动化</h3>
<p>现如今我们可以通过 HTTP（Hypertext transfer protocol 超文本传输协议）请求对应的 API 来实现绝大部分程序的功能，因此自动调用公共 API 是最常见的自动化程序。例如，如果你需要给你家的花园实现自动化灌溉。</p>
<p>为此，你需要根据当天天气来决定是要浇水还是有雨要来。</p>
<h3 id="api">API 的逆向工程</h3>
<p>在实际的程序中，基于 API 逆向工程的自动化程序更为常见。在下文的“自动化的道德考量”中也会探讨机器人冒名顶替真是人类的问题</p>
<p>通过对一个 API 进行逆向工程，我们可以了解用户在某个应用中的操作流程。例如登录一个网页游戏的步骤。</p>
<p>通过理解登录和身份验证的逻辑，我们可以使用脚本来复制这一动作。然后即使他们不对外提供应用界面，我们也可以创建自己的接口脚本来使用他们的应用。</p>
<p>无论你是出什么目的，请考虑一下它是否合法。</p>
<p>你也不想惹麻烦，对吧？😁</p>
<h2 id="">道德考量</h2>
<p>GitHub 上有个人联系到我说：</p>
<blockquote>
<p>“点赞数和订阅数就是数字时代的货币，但是你们正在让它贬值。”</p>
</blockquote>
<p>This stuck with me and made me question the tool I've built for exactly that purpose.<br>
我一直思考着这个问题，并开始质疑我构建程序真正的目的是什么。</p>
<p>事实是，这些互动和点赞可以通过自动化的方式进行伪造，这种伪造越来越多，导致扭曲和破坏了社交媒体的正常运行。</p>
<p>如果不使用机器人或者其他的刷赞系统，用户和广告公司将看不到那些真正产出好内容并创造价值的人</p>
<p>我的一个朋友借助但丁《神曲》中《地狱篇》的“九层地狱”的情景，来向我解释随着你社会影响力的一步步扩大，你越来越难以意识到这个系统实际的破败之处。</p>
<p>我想和你分享这个观点，因为我认为这能非常准确的描述在我使用 InstaPy 工具与网红合作期间所看到的一切。</p>
<p><strong>第一层：灵薄狱</strong></p>
<p>假如你不使用机器人。</p>
<p><strong>第二层：纵欲</strong></p>
<p>当你手动的开始点赞和关注尽可能多的人，并让他们也点赞和关注你的文章。</p>
<p><strong>第三层：暴食</strong></p>
<p>当你加入一个 Telegram 群，大家点赞并评论 10 张照片，那么接下来的 10 个人也会点赞并评论你的照片。</p>
<p><strong>第四层：贪婪</strong></p>
<p>当你使用低成本的虚拟助手帮你点赞和关注。</p>
<p><strong>第五层：愤怒</strong></p>
<p>当你使用机器人去点赞，但是没有任何点赞的回馈（但是你不用付费，例如 Chrome 游览器中的扩展程序）。</p>
<p><strong>第六层：异端</strong></p>
<p>当你使用机器人给出 50+个点赞并获得 50+个点赞（但是你不用付费，例如 Chrome 游览器中的扩展程序）。</p>
<p><strong>第七层：施暴</strong></p>
<p>当你使用机器人点赞、关注、评论 200-700 张照片，并无视禁言的警告。</p>
<p><strong>第八层：欺诈</strong></p>
<p>当你付费给未知的第三方服务去自动的帮你获得点赞和关注，同时也用你的账号去点赞和关注别人。</p>
<p><strong>第九层：背叛者</strong></p>
<p>当你付费购买点赞和关注数，试图去包装自己成为一个网红。</p>
<p>在社交媒体上面使用机器人非常常见，以致于<strong>如果你不包装，你会被卡在第一层，即灵薄狱</strong>，与你的同行比起来你的关注人数没有增长，订阅量也低。</p>
<p>从经济型理论看，这叫<strong>囚徒困境和零和博弈</strong>。如果我不使用机器人，但是你用了，你就赢了。如果你没有用，但我用了，我就赢了。如果我们都不用，那么我们就能共赢。但是对于那些没有使用机器人的人是没有奖励的，大家就都在用，那么没有人会赢。</p>
<blockquote>
<p>请警惕这点，不要忘记整个工具对社交媒体的影响。</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/spectrum-bot-intent-ebook.png" alt="spectrum-bot-intent-ebook" width="600" height="400" loading="lazy"></p>
<p>来源：SignalSciences.com</p>
<p>我们希望规避道德问题，并继续开展一个自动化的项目。这就是我们为什么只是创建一个简单的目录整理脚本来帮祝你整理乱糟糟的文件。</p>
<h2 id="">创建整理目录脚本</h2>
<p>现在让我们来看一个非常简单的脚本。它会自动整理指定的目录，将其中的文件根据文件后缀名移动到对于的文件夹。</p>
<p>下图就是我们将要做的事情：</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/directory_clean_img.png" alt="directory_clean_img" width="600" height="400" loading="lazy"></p>
<h3 id="">设置参数解析器</h3>
<p>由于我们会用到操作系统的功能，比如移动文件，所以我们需要导入 <code>os</code> 库。除此之外，我们还希望用户能够控制要整理的文件夹，因此我们还会用到 <code>argparse</code> 库。</p>
<pre><code class="language-python">import os
import argparse
</code></pre>
<p>导入了这两个库之后，我们首先要设置参数解析器。确保为每个参数有对应的描述和帮助文本，以便用户在输入 <code>--help</code> 时得到帮助。</p>
<p>我们的参数会被命名为 <code>--path</code>。 参数名前面的双破折号告诉库这是一个可选参数。默认情况下，我们使用当前目录，因此将默认值设为 <code>.</code>。</p>
<pre><code class="language-python">parser = argparse.ArgumentParser(
    description="Clean up directory and put files into according folders."
)

parser.add_argument(
    "--path",
    type=str,
    default=".",
    help="Directory path of the to be cleaned directory",
)
# 解析用户提供的path参数的值
args = parser.parse_args()
path = args.path

print(f"Cleaning up directory {path}")
</code></pre>
<p>这就完成了参数解析的部分，非常简单易读，对吧？</p>
<p>让我们执行一下脚本，检查是否有报错。</p>
<pre><code class="language-bash">python directory_clean.py --path ./test

=&gt; Cleaning up directory ./test

</code></pre>
<p>一旦执行，我们可以在控制台中看到目录名称被打印出来，完美。</p>
<p>现在让我们来使用 <code>os</code> 库来获取给定路径下的文件。</p>
<h3 id="">从文件夹中获取文件列表</h3>
<p>通过给 <code>os.listdir(path)</code> 方法提供一个有效的路径，我们就能获得该目录内所有文件和文件夹的列表。</p>
<p>在列出了文件夹内所有的元素后，我们需要对文件和文件夹进行区分，因为我们只需要整理文件而不是文件夹。</p>
<p>我们使用 Python 的列表来遍历所有元素，根据是否满足是文件还是文件夹的条件将他们放到新的列表中。</p>
<pre><code class="language-python"># 获取目录中的所有文件
dir_content = os.listdir(path)
# 根据文件和文件名创建相对路径
path_dir_content = [os.path.join(path, doc) for doc in dir_content]
# 过滤目录内容到文档或文件夹列表
docs = [doc for doc in path_dir_content if os.path.isfile(doc)]
folders = [folder for folder in path_dir_content if os.path.isdir(folder)]
# 记录文件移动的数量
# 列出已经创建的文件夹以免出现重复
moved = 0
created_folders = []

print(f"Cleaning up {len(docs)} of {len(dir_content)} elements.")
</code></pre>
<p>和之前一样，让我们确保用户能够得到反馈。所以需要打印一个告知用户多少文件被移动的信息。</p>
<pre><code class="language-bash">python directory_clean.py --path ./test

=&gt; Cleaning up directory ./test
=&gt; Cleaning up 60 of 60 elements.
</code></pre>
<p>当我们再次执行 python 脚本之后，我们可以看到在 <code>/test</code> 文件夹下将会出现 60 个被移动的文件。</p>
<h3 id="">根据文件后缀名创建文件夹</h3>
<p>接下来也是最重要的一步是根据每个文件的后缀名创建文件夹。我们希望通过遍历所有已经过滤好的文件，如果没有创建对应后缀名的文件夹，就创建一个。</p>
<p><code>os</code> 库能给我们提供非常友好的功能，例如拆分给定文件的类型和路径，提取文件路径和文件名。</p>
<pre><code class="language-python"># 遍历所有的文件，并移动到对应的文件夹中
for doc in docs:
    # 提取文件后缀名
    full_doc_path, filetype = os.path.splitext(doc)
    doc_path = os.path.dirname(full_doc_path)
    doc_name = os.path.basename(full_doc_path)

    print(filetype)
    print(full_doc_path)
    print(doc_path)
    print(doc_name)

    break
</code></pre>
<p>如果我们的目录包含成堆的文件，那么上面代码末尾的 break 语句用于确保我们的终端不会列满所有的文件信息。</p>
<p>我们设置好这一步之后，让我们执行一下脚本，看到的内容可能类似这样的：</p>
<pre><code class="language-python">python directory_clean.py --path ./test

=&gt; ...
=&gt; .pdf
=&gt; ./test/test17
=&gt; ./test
=&gt; test17
</code></pre>
<p>我们可以通过上面的实现，分离文件类型，然后从完整路径中提取部分内容。</p>
<p>现在我们有了文件类型，我们就能检查拥有这个文件类型的同名文件夹是否已经存在。</p>
<p>在开始这一步之前，我们需要跳过一些文件。如果我们使用当前目录 <code>.</code> 作为路径，我们需要避免 python 脚本也被移动。可以通过一个简单的 if 条件语句来解决这个问题。</p>
<p>另外，我们也不希望移动<a href="https://www.lifewire.com/what-is-a-hidden-file-2625898">隐藏文件</a>，所有 <code>.</code> 开头的文件也要跳过。 macOS 上的 <code>.DS_Store</code> 就是一个例子。</p>
<pre><code class="language-python">    # 当在目录中存在 名为 directory_clean 的文件或 . 开头的文件在时跳过
    if doc_name == "directory_clean" or doc_name.startswith('.'):
        continue
    # 获得子文件夹的名称，创建其中不存在的文件夹名
    subfolder_path = os.path.join(path, filetype[1:].lower())

    if subfolder_path not in folders:
        # 创建文件夹

</code></pre>
<p>处理完 python 脚本路径和隐藏文件后，我们可以继续在系统中创建文件夹了。</p>
<p>除了我们的判断之外，如果一开始读取目录时发现同名文件夹已经存在，我们需要一种能够检测已创建文件夹的方法。这就是我们要声明数组变量 <code>create_folders = []</code> 的原因。它将用来存储已被检测过的文件名。</p>
<p><code>os</code> 库中提供了一个 <code>os.mkdir(folder_path)</code> 的方法用于根据路径创建新文件夹。</p>
<p>这个方法可能会抛出异常，告诉我们文件夹已经存在。所以我们需要确保异常被捕获。</p>
<pre><code class="language-python">if subfolder_path not in folders and subfolder_path not in created_folders:
    try:
        os.mkdir(subfolder_path)
        created_folders.append(subfolder_path)
        print(f"Folder {subfolder_path} created.")
    except FileExistsError as err:
        print(f"Folder already exists at {subfolder_path}... {err}")

</code></pre>
<p>在编写完创建文件夹的代码后，让我们重新运行一遍脚本。</p>
<pre><code class="language-python">python directory_clean.py --path ./test 

=&gt; ...
=&gt; Folder ./test/pdf created.
</code></pre>
<p>在第一次执行时，我们从日志列表看到，我们已经创建了以文件后缀名命名的文件夹。</p>
<p>最后一步就是移动文件到它们对应的父文件夹中。</p>
<p>当使用 <code>os</code> 库时需要明白的最重要的一点是，有些操作无法撤销。例如，删除文件的情况。因此，在执行脚本前我们需要先注释掉部分内容</p>
<p>这也是为什么我们的 <code>os.rename(...)</code> 方法会在这里被注释掉。</p>
<pre><code class="language-python"># 获取新文件路径，移动文件
    new_doc_path = os.path.join(subfolder_path, doc_name) + filetype
    # os.rename(doc, new_doc_path)
    moved += 1

    print(f"Moved file {doc} to {new_doc_path}")
</code></pre>
<p>运行完我们的脚本并看到正确的日志之后，我们可以撤销 <code>os.rename()</code> 方法的注释，并最终写成这样的。</p>
<pre><code class="language-python"># 获取新文件路径，移动文件
    new_doc_path = os.path.join(subfolder_path, doc_name) + filetype
    os.rename(doc, new_doc_path)
    moved += 1

    print(f"Moved file {doc} to {new_doc_path}")

print(f"Renamed {moved} of {len(docs)} files.")
</code></pre>
<pre><code class="language-bash">python directory_clean.py --path ./test

=&gt; ...
=&gt; Moved file ./test/test17.pdf to ./test/pdf/test17.pdf
=&gt; ...
=&gt; Renamed 60 of 60 files.
</code></pre>
<p>最后的这个运行结果会将所有文件移动到对应的文件夹中，我们的目录不需要手动操作也能很好的被整理。</p>
<p>下一步，我们可以利用我们上面创建好的脚本去做更多是事情，例如，安排脚本在每个星期一定时清理 Downloads 文件夹，以便让其看起来更整洁有序。</p>
<p><strong>这也是我们在 Udemy 中创建的名为<a href="https://www.udemy.com/course/the-complete-guide-to-bot-creation/?referralCode=7418EBB47E11E34D86C9">创建自动化程序</a>的后续课程</strong></p>
<h2 id=""><a href="https://www.udemy.com/course/the-complete-guide-to-bot-creation/?referralCode=7418EBB47E11E34D86C9">一份完整的日常自动化程序指南</a></h2>
<p>Felix 和我在学习 <strong>InstaPy</strong> 库和他的 <strong>Travian-Bot</strong> 库的基础上创建了一个<strong>教你如何创建自己的机器人</strong>的在线视频。实际上，他也因为这个库太火爆导致想关闭这个项目。</p>
<!--kg-card-end: markdown--><p>原文：<a href="https://www.freecodecamp.org/news/building-bots/">How to Build a Bot and Automate your Everyday Work</a>，作者：<a href="https://www.freecodecamp.org/news/author/timgrossmann/">Tim Grossmann</a></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 左手抽象语法树，右手自动化编程 ]]>
                </title>
                <description>
                    <![CDATA[ > 随着软件开发技术的不断进步，处理偶发复杂度的行为都有可能被自动化、被机器取代；只有处理本质复杂度的建模行为，无法被机器取代。 —— 熊大 引用上面一段话，是因为它很好地点出了这几年我一直专注的方向，如何让技术工作者专注于无法被机器取代的部分，而不是拼体力去和自动化机器抢生意。 再不努力你就要被机器取代！ 为什么会有这种焦虑？并不是源于现在网络上一直吹嘘的人工智能，而是来自自我反省。 最近在研究一些代码质量分析系统的时候，其中有一项就是代码的重复率。意思就是你一直以来提交的代码里，在做多少重复的劳动？ 且不论这个系统的科学性和准确性，但它的确给了我一个声音，我从直觉是感到自己平时也写很多重复代码。 好了，感慨完进入正题。首先，怎么找到重复劳动？ 我们看一段代码： import * as mongoose from 'mongoose'; enum Lang { js, java, c } export interface IUserModel extends mongoose.Document {   name: string;   age: number;   ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/practice-in-ast-and-code-gen/</link>
                <guid isPermaLink="false">5ffd5b195f61e30501b5b796</guid>
                
                    <category>
                        <![CDATA[ 自动化 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ 开发者小蓝 ]]>
                </dc:creator>
                <pubDate>Tue, 12 Jan 2021 09:18:33 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2021/01/martin-shreder-5Xwaj9gaR0g-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <blockquote>
<p>随着软件开发技术的不断进步，处理偶发复杂度的行为都有可能被自动化、被机器取代；只有处理本质复杂度的建模行为，无法被机器取代。 —— 熊大</p>
</blockquote>
<p>引用上面一段话，是因为它很好地点出了这几年我一直专注的方向，如何让技术工作者专注于无法被机器取代的部分，而不是拼体力去和自动化机器抢生意。</p>
<h4 id="">再不努力你就要被机器取代！</h4>
<p>为什么会有这种焦虑？并不是源于现在网络上一直吹嘘的人工智能，而是来自自我反省。</p>
<p><img src="https://lanhaooss.oss-cn-shenzhen.aliyuncs.com/images/329/1.png" alt="1" width="600" height="400" loading="lazy"></p>
<p>最近在研究一些代码质量分析系统的时候，其中有一项就是代码的重复率。意思就是你一直以来提交的代码里，在做多少重复的劳动？</p>
<p>且不论这个系统的科学性和准确性，但它的确给了我一个声音，我从直觉是感到自己平时也写很多重复代码。</p>
<h4 id="">好了，感慨完进入正题。首先，怎么找到重复劳动？</h4>
<p>我们看一段代码：</p>
<pre><code>import * as mongoose from 'mongoose';

enum Lang { js, java, c }

export interface IUserModel extends mongoose.Document {
  name: string;
  age: number;
  language: Lang;
}

const schema = new mongoose.Schema(
  {
    name: {
      type: String,
      require: true, 
    },
    age: {
      type: Number,
      require: true, 
    },
    language: {
      type: Lang,
      require: true, 
      enum: [ Lang.js, Lang.java, Lang.c ],
    },
  },
  {
    usePushEach: true,
    timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' },
  },
);

export default mongoose.model('user', schema);

</code></pre>
<p>如何识别上面的重复代码？表面看来，真正在运行中有用的部分，是 <code>new mongoose/Schema(...)</code> 这部分，但我们判断的依据并不在此。</p>
<blockquote>
<p>代码编写实际上是体现了我们的主观意图。</p>
</blockquote>
<p>抛开其他庞杂的知识体系，在这段代码里，我们的主观意图是<strong>定义一个用户类型的模型</strong>。再简化一下，就是<strong>定义用户类型</strong>。</p>
<p>所以我思考上面这几十行代码，哪些是代表我自己的主观意图，哪些是机器没法代替的部分呢？</p>
<p>其实仅仅是用户接口类型的定义：</p>
<pre><code>enum Lang { js, java, c }

export interface IUserModel extends mongoose.Document {
  name: string;
  age: number;
  language: Lang;
}
</code></pre>
<p>至于如何使用 <code>mongoose</code>去定义一个 <code>Schema</code>，再导出一个<code>Model</code>实例，这些每次都要我翻看在线文档的操作，我恨不得交给计算机去做。</p>
<p><img src="https://lanhaooss.oss-cn-shenzhen.aliyuncs.com/images/329/2.jpg" alt="2" width="600" height="400" loading="lazy"></p>
<p><strong>而接下来我就是要让计算机来完成这个任务。</strong></p>
<blockquote>
<p>🤡 这个真的可行吗？</p>
<p>🤖 理论上是可以的，只要你确定某些操作，完全没有注入自己的脑力创作元素，那它一定可以被计算机替代。</p>
</blockquote>
<p>如果这真的可以做到，那么理想情况下，我们需要自己编写的代码，只剩下这些。</p>
<pre><code>import * as mongoose from 'mongoose';

enum Lang { js, java, c }

export interface IUserModel extends mongoose.Document {
  name: string;
  age: number;
  language: Lang;
}
</code></pre>
<p>很好，只定义了一个用户的接口类型，符合我们的主观意图。</p>
<p>然后使用程序<strong>分析这段代码</strong>：</p>
<pre><code>//  因为讲解需要，对原始 AST 输出做了简化，突出重点

[
  {
    type: 'ImportDeclaration',
    source: {
      value: 'mongoose'
    },
  },
  {
    type: 'TSEnumDeclaration',
    id: { type: 'Identifier', name: 'Lang' },
    members: [ 'js', 'java', 'c' ]
  },
  {
    type: 'ExportNamedDeclaration',
    declaration: {
      type: 'TSInterfaceDeclaration',
      body: [{...},{...},{...}],
      id: { name: 'IUserModel' },
      extends: ['Document']
    },
  }
]

</code></pre>
<p>可见，我们只写了三行代码：</p>
<ol>
<li>引入一个依赖 mongoose</li>
<li>定义了 Lang 枚举类型</li>
<li>导出了 用户接口，继承自 Document</li>
</ol>
<p>从以上信息里，我需要机器人捕捉到的关键是第三行代码🔍。</p>
<p>我们可以根据<code>AST</code>结构的特征，让机器人只处理 <code>TSInterfaceDeclaration </code>并且 <code>extends</code> 自 <code>Document</code>的，这个逻辑简单，自然是不需要贴代码的，大家都能理解。</p>
<h4 id="tsinterfacedeclaration">然后我们需要让机器人明白我们的  <code>TSInterfaceDeclaration </code> 语句，定义了一个怎样的（包含哪些字段类型）的接口类型。</h4>
<p>我们再展开一下上面的 <code>body: [{...},{...},{...}],</code></p>
<pre><code>// 因为讲解需要，对原始 AST 输出做了简化，突出重点

[
  {
    key: { name: 'name' },
    typeAnnotation: {
      type: 'TSStringKeyword',
    }
  },
  {
    key: { name: 'age' },
    typeAnnotation: {
      type: 'TSNumberKeyword',
    }
  },
  {
    key: { name: 'language' },
    typeAnnotation: {
      type: 'TSTypeReference',
      typeName: { name: 'Lang' }
    }
  }
]
</code></pre>
<p>这部分如果比较晦涩，可以对照着 <code>IUserModel</code>的定义，就很好读懂了。</p>
<p>主要就是表达了<code>IUserModel</code>里三个字段的类型定义，已经能清楚看出<code>name</code>是一个字符串类型，<code>age</code>是一个数字类型，而<code>language</code>则是一个<code>Lang</code>的引用类型。</p>
<h4 id="">分析完毕，重复工作一次编写</h4>
<p>代码分析环节到这里几乎就到了柳暗花明枯木逢春的境地了。</p>
<p>我们的主观意图很好地传递给了机器人，然后，我们让机器人根据 <strong>mongoose文档</strong> 的要求，书写后续的 <code>Schema</code>和<code>Model</code>。</p>
<p>因为 <code>TS</code>的类型定义，比如<code>TSStringKeyword </code>， 也就是我们平时书写的 <code>:string</code>，总能找到一个对应的<code>mongoose SchemaType</code>，比如 <code>mongoose.Schema.Types.String</code>。</p>
<p><strong>我们平时就是花了比较多的时间在写这种重复代码。</strong></p>
<p>最后，因为本文并不是工具开发介绍，就不贴具体实现了。如果有人感兴趣，后续我视情况再写一篇《实践》。</p>
<p>送一个动图，证明我没说谎。</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/news/content/images/2021/01/3.gif" class="kg-image" alt="3" width="600" height="400" loading="lazy"></figure> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
