Full Code of 521xueweihan/GitHub520 for AI

main a1cd17e46a56 cached
12 files
27.6 KB
9.0k tokens
14 symbols
1 requests
Download .txt
Repository: 521xueweihan/GitHub520
Branch: main
Commit: a1cd17e46a56
Files: 12
Total size: 27.6 KB

Directory structure:
gitextract_btmf6xsu/

├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── GitHub520.yml
├── .gitignore
├── README.md
├── README_template.md
├── actions_requirements.txt
├── common.py
├── fetch_ips.py
├── hosts
├── hosts.json
├── requirements.txt
└── update_ips.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: [521xueweihan]
custom: ['https://hellogithub.com/', 'https://mp.weixin.qq.com/s/xNpX3eCaWL_kNe8oZLxTWA']


================================================
FILE: .github/workflows/GitHub520.yml
================================================
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: GitHub520

on:
  push:
  schedule:
    - cron: '0 */2 * * *'

jobs:
  build:

    runs-on: ubuntu-24.04
    strategy:
      matrix:
        python-version: [3.9]

    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: |
        if [ -f actions_requirements.txt ]; then pip install -r actions_requirements.txt; fi
    - name: run script
      run: |
        # fetch new ip content and update readme file
        python update_ips.py
    - name: commit
      id: commit
      run: |
        git config --global user.email sunxuebangong@gmail.com
        git config --global user.name action_bot
        git add .
        git commit -m "update readme content"
      continue-on-error: true
    - name: Check on failures
      if: steps.commit.outputs.status == 'failure'
      run: exit 1
    - name: Push changes
      uses: ad-m/github-push-action@master
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/
.idea/
.DS_Store


================================================
FILE: README.md
================================================
# GitHub520

<p align="center">
<a href="https://hellogithub.com/repository/d05ff820bf36470581c02cda5cbd17ea" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=d05ff820bf36470581c02cda5cbd17ea&claim_uid=8MKvZoxaWt" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a><br>
😘 让你“爱”上 GitHub,解决访问时图裂、加载慢的问题。
</p>

> 💰服务器将于 2025-12-31 到期,续费需要 831 元/年 [点击扫码赞助](https://raw.hellogithub.com/code.png),感谢🙏

## 一、介绍
对 GitHub 说"爱"太难了:访问慢、图片加载不出来。

**本项目无需安装任何程序,仅需 5 分钟。**

通过修改本地 hosts 文件,试图解决:
- GitHub 访问速度慢的问题
- GitHub 项目中的图片显示不出的问题

让你"爱"上 GitHub。



*注:* 本项目还处于测试阶段,仅在本机测试通过,如有问题欢迎提 [issues](https://github.com/521xueweihan/GitHub520/issues/new)


## 二、使用方法

下面的地址无需访问 GitHub 即可获取到最新的 hosts 内容:

- 文件:`https://raw.hellogithub.com/hosts`
- JSON:`https://raw.hellogithub.com/hosts.json`

### 2.1 手动方式

#### 2.1.1 复制下面的内容

```bash
# GitHub520 Host Start
140.82.113.25                 alive.github.com
20.205.243.168                api.github.com
140.82.114.22                 api.individual.githubcopilot.com
185.199.110.133               avatars.githubusercontent.com
185.199.110.133               avatars0.githubusercontent.com
185.199.110.133               avatars1.githubusercontent.com
185.199.110.133               avatars2.githubusercontent.com
185.199.110.133               avatars3.githubusercontent.com
185.199.110.133               avatars4.githubusercontent.com
185.199.110.133               avatars5.githubusercontent.com
185.199.110.133               camo.githubusercontent.com
140.82.112.21                 central.github.com
185.199.110.133               cloud.githubusercontent.com
20.205.243.165                codeload.github.com
140.82.114.21                 collector.github.com
185.199.110.133               desktop.githubusercontent.com
185.199.110.133               favicons.githubusercontent.com
140.82.112.3                  gist.github.com
52.217.75.116                 github-cloud.s3.amazonaws.com
52.217.119.65                 github-com.s3.amazonaws.com
16.15.193.93                  github-production-release-asset-2e65be.s3.amazonaws.com
54.231.232.73                 github-production-repository-file-5c1aeb.s3.amazonaws.com
52.217.226.249                github-production-user-asset-6210df.s3.amazonaws.com
192.0.66.2                    github.blog
20.205.243.166                github.com
140.82.114.17                 github.community
185.199.108.154               github.githubassets.com
151.101.193.194               github.global.ssl.fastly.net
185.199.111.153               github.io
185.199.110.133               github.map.fastly.net
185.199.111.153               githubstatus.com
140.82.113.26                 live.github.com
185.199.110.133               media.githubusercontent.com
185.199.110.133               objects.githubusercontent.com
13.107.42.16                  pipelines.actions.githubusercontent.com
185.199.110.133               raw.githubusercontent.com
185.199.110.133               user-images.githubusercontent.com
13.107.213.73                 vscode.dev
140.82.112.22                 education.github.com
185.199.110.133               private-user-images.githubusercontent.com


# Update time: 2026-03-20T14:25:11+08:00
# Update url: https://raw.hellogithub.com/hosts
# Star me: https://github.com/521xueweihan/GitHub520
# GitHub520 Host End

```

该内容会自动定时更新, 数据更新时间:2026-03-20T14:25:11+08:00

#### 2.1.2 修改 hosts 文件

hosts 文件在每个系统的位置不一,详情如下:
- Windows 系统:`C:\Windows\System32\drivers\etc\hosts`
- Linux 系统:`/etc/hosts`
- Mac(苹果电脑)系统:`/etc/hosts`
- Android(安卓)系统:`/system/etc/hosts`
- iPhone(iOS)系统:`/etc/hosts`

修改方法,把第一步的内容复制到文本末尾:

1. Windows 使用记事本。
2. Linux、Mac 使用 Root 权限:`sudo vi /etc/hosts`。
3. iPhone、iPad 须越狱、Android 必须要 root。

#### 2.1.3 激活生效
大部分情况下是直接生效,如未生效可尝试下面的办法,刷新 DNS:

1. Windows:在 CMD 窗口输入:`ipconfig /flushdns`

2. Linux 命令:`sudo nscd restart`,如报错则须安装:`sudo apt install nscd` 或 `sudo /etc/init.d/nscd restart`

3. Mac 命令:`sudo killall -HUP mDNSResponder`

**Tips:** 上述方法无效可以尝试重启机器。

### 2.2 自动方式(SwitchHosts)

**Tip**:推荐 [SwitchHosts](https://github.com/oldj/SwitchHosts) 工具管理 hosts

以 SwitchHosts 为例,看一下怎么使用的,配置参考下面:

- Hosts 类型: `Remote`

- Hosts 标题: 随意

- URL: `https://raw.hellogithub.com/hosts`

- 自动刷新: 最好选 `1 小时`

如图:

![](./img/switch-hosts.png)

这样每次 hosts 有更新都能及时进行更新,免去手动更新。

### 2.3 一行命令

#### Windows

使用命令需要安装[git bash](https://gitforwindows.org/)
复制以下命令保存到本地命名为**fetch_github_hosts**

```shell
_hosts=$(mktemp /tmp/hostsXXX)
hosts=/c/Windows/System32/drivers/etc/hosts
remote=https://raw.hellogithub.com/hosts
reg='/# GitHub520 Host Start/,/# Github520 Host End/d'

sed "$reg" $hosts > "$_hosts"
curl "$remote" >> "$_hosts"
cat "$_hosts" > "$hosts"

rm "$_hosts"
```

在**CMD**中执行以下命令,执行前需要替换**git-bash.exe**和**fetch_github_hosts**为你本地的路径,注意前者为windows路径格式后者为shell路径格式

`"C:\Program Files\Git\git-bash.exe" -c "/c/Users/XXX/fetch_github_hosts"`

可以将上述命令添加到windows的task schedular(任务计划程序)中以定时执行

#### GNU(Ubuntu/CentOS/Fedora)

`sudo sh -c 'sed -i "/# GitHub520 Host Start/Q" /etc/hosts && curl https://raw.hellogithub.com/hosts >> /etc/hosts'`

#### BSD/macOS

`sudo sed -i "" "/# GitHub520 Host Start/,/# Github520 Host End/d" /etc/hosts && curl https://raw.hellogithub.com/hosts | sudo tee -a /etc/hosts`

将上面的命令添加到 cron,可定时执行。使用前确保 GitHub520 内容在该文件最后部分。

**在 Docker 中运行,若遇到 `Device or resource busy` 错误,可使用以下命令执行**

`cp /etc/hosts ~/hosts.new && sed -i "/# GitHub520 Host Start/Q" ~/hosts.new && curl https://raw.hellogithub.com/hosts >> ~/hosts.new && cp -f ~/hosts.new /etc/hosts`

### 2.4 AdGuard 用户(自动方式)

在 **过滤器>DNS 封锁清单>添加阻止列表>添加一个自定义列表**,配置如下:

- 名称:随意

- URL:`https://raw.hellogithub.com/hosts`(和上面 SwitchHosts 使用的一样)

如图:

![](./img/AdGuard-rules.png)

更新间隔在 **设置 > 常规设置 > 过滤器更新间隔(设置一小时一次即可)**,记得勾选上 **使用过滤器和 Hosts 文件以拦截指定域名**

![](./img/AdGuard-rules2.png)

**Tip**:不要添加在 **DNS 允许清单** 内,只能添加在 **DNS 封锁清单** 才管用。 另外,AdGuard for Mac、AdGuard for Windows、AdGuard for Android、AdGuard for IOS 等等 **AdGuard 家族软件** 添加方法均类似。


## 三、效果对比
之前的样子:

![](./img/old.png)

修改完 hosts 的样子:

![](./img/new.png)


## TODO
- [x] 定时自动更新 hosts 内容
- [x] hosts 内容无变动不会更新
- [x] 寻到最优 IP 解析结果

## 声明
<a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh"><img alt="知识共享许可协议" style="border-width: 0" src="https://licensebuttons.net/l/by-nc-nd/4.0/88x31.png"></a><br>本作品采用 <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh">署名-非商业性使用-禁止演绎 4.0 国际</a> 进行许可。


================================================
FILE: README_template.md
================================================
# GitHub520

<p align="center">
<a href="https://hellogithub.com/repository/d05ff820bf36470581c02cda5cbd17ea" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=d05ff820bf36470581c02cda5cbd17ea&claim_uid=8MKvZoxaWt" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a><br>
😘 让你“爱”上 GitHub,解决访问时图裂、加载慢的问题。
</p>

> 💰服务器将于 2025-12-31 到期,续费需要 831 元/年 [点击扫码赞助](https://raw.hellogithub.com/code.png),感谢🙏

## 一、介绍
对 GitHub 说"爱"太难了:访问慢、图片加载不出来。

**本项目无需安装任何程序,仅需 5 分钟。**

通过修改本地 hosts 文件,试图解决:
- GitHub 访问速度慢的问题
- GitHub 项目中的图片显示不出的问题

让你"爱"上 GitHub。



*注:* 本项目还处于测试阶段,仅在本机测试通过,如有问题欢迎提 [issues](https://github.com/521xueweihan/GitHub520/issues/new)


## 二、使用方法

下面的地址无需访问 GitHub 即可获取到最新的 hosts 内容:

- 文件:`https://raw.hellogithub.com/hosts`
- JSON:`https://raw.hellogithub.com/hosts.json`

### 2.1 手动方式

#### 2.1.1 复制下面的内容

```bash
{hosts_str}
```

该内容会自动定时更新, 数据更新时间:{update_time}

#### 2.1.2 修改 hosts 文件

hosts 文件在每个系统的位置不一,详情如下:
- Windows 系统:`C:\Windows\System32\drivers\etc\hosts`
- Linux 系统:`/etc/hosts`
- Mac(苹果电脑)系统:`/etc/hosts`
- Android(安卓)系统:`/system/etc/hosts`
- iPhone(iOS)系统:`/etc/hosts`

修改方法,把第一步的内容复制到文本末尾:

1. Windows 使用记事本。
2. Linux、Mac 使用 Root 权限:`sudo vi /etc/hosts`。
3. iPhone、iPad 须越狱、Android 必须要 root。

#### 2.1.3 激活生效
大部分情况下是直接生效,如未生效可尝试下面的办法,刷新 DNS:

1. Windows:在 CMD 窗口输入:`ipconfig /flushdns`

2. Linux 命令:`sudo nscd restart`,如报错则须安装:`sudo apt install nscd` 或 `sudo /etc/init.d/nscd restart`

3. Mac 命令:`sudo killall -HUP mDNSResponder`

**Tips:** 上述方法无效可以尝试重启机器。

### 2.2 自动方式(SwitchHosts)

**Tip**:推荐 [SwitchHosts](https://github.com/oldj/SwitchHosts) 工具管理 hosts

以 SwitchHosts 为例,看一下怎么使用的,配置参考下面:

- Hosts 类型: `Remote`

- Hosts 标题: 随意

- URL: `https://raw.hellogithub.com/hosts`

- 自动刷新: 最好选 `1 小时`

如图:

![](./img/switch-hosts.png)

这样每次 hosts 有更新都能及时进行更新,免去手动更新。

### 2.3 一行命令

#### Windows

使用命令需要安装[git bash](https://gitforwindows.org/)
复制以下命令保存到本地命名为**fetch_github_hosts**

```shell
_hosts=$(mktemp /tmp/hostsXXX)
hosts=/c/Windows/System32/drivers/etc/hosts
remote=https://raw.hellogithub.com/hosts
reg='/# GitHub520 Host Start/,/# Github520 Host End/d'

sed "$reg" $hosts > "$_hosts"
curl "$remote" >> "$_hosts"
cat "$_hosts" > "$hosts"

rm "$_hosts"
```

在**CMD**中执行以下命令,执行前需要替换**git-bash.exe**和**fetch_github_hosts**为你本地的路径,注意前者为windows路径格式后者为shell路径格式

`"C:\Program Files\Git\git-bash.exe" -c "/c/Users/XXX/fetch_github_hosts"`

可以将上述命令添加到windows的task schedular(任务计划程序)中以定时执行

#### GNU(Ubuntu/CentOS/Fedora)

`sudo sh -c 'sed -i "/# GitHub520 Host Start/Q" /etc/hosts && curl https://raw.hellogithub.com/hosts >> /etc/hosts'`

#### BSD/macOS

`sudo sed -i "" "/# GitHub520 Host Start/,/# Github520 Host End/d" /etc/hosts && curl https://raw.hellogithub.com/hosts | sudo tee -a /etc/hosts`

将上面的命令添加到 cron,可定时执行。使用前确保 GitHub520 内容在该文件最后部分。

**在 Docker 中运行,若遇到 `Device or resource busy` 错误,可使用以下命令执行**

`cp /etc/hosts ~/hosts.new && sed -i "/# GitHub520 Host Start/Q" ~/hosts.new && curl https://raw.hellogithub.com/hosts >> ~/hosts.new && cp -f ~/hosts.new /etc/hosts`

### 2.4 AdGuard 用户(自动方式)

在 **过滤器>DNS 封锁清单>添加阻止列表>添加一个自定义列表**,配置如下:

- 名称:随意

- URL:`https://raw.hellogithub.com/hosts`(和上面 SwitchHosts 使用的一样)

如图:

![](./img/AdGuard-rules.png)

更新间隔在 **设置 > 常规设置 > 过滤器更新间隔(设置一小时一次即可)**,记得勾选上 **使用过滤器和 Hosts 文件以拦截指定域名**

![](./img/AdGuard-rules2.png)

**Tip**:不要添加在 **DNS 允许清单** 内,只能添加在 **DNS 封锁清单** 才管用。 另外,AdGuard for Mac、AdGuard for Windows、AdGuard for Android、AdGuard for IOS 等等 **AdGuard 家族软件** 添加方法均类似。


## 三、效果对比
之前的样子:

![](./img/old.png)

修改完 hosts 的样子:

![](./img/new.png)


## TODO
- [x] 定时自动更新 hosts 内容
- [x] hosts 内容无变动不会更新
- [x] 寻到最优 IP 解析结果

## 声明
<a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh"><img alt="知识共享许可协议" style="border-width: 0" src="https://licensebuttons.net/l/by-nc-nd/4.0/88x31.png"></a><br>本作品采用 <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh">署名-非商业性使用-禁止演绎 4.0 国际</a> 进行许可。


================================================
FILE: actions_requirements.txt
================================================
requests-html==0.10.0
retry==0.9.2
lxml_html_clean

================================================
FILE: common.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
#   Author  :   XueWeiHan
#   E-mail  :   595666367@qq.com
#   Date    :   2025-01-16 15:27
#   Desc    :   公共函数
import os
import json
from typing import Any, Optional
from datetime import datetime, timezone, timedelta

from retry import retry

GITHUB_URLS = [
    'alive.github.com', 'api.github.com', 'api.individual.githubcopilot.com',
    'avatars.githubusercontent.com', 'avatars0.githubusercontent.com',
    'avatars1.githubusercontent.com', 'avatars2.githubusercontent.com',
    'avatars3.githubusercontent.com', 'avatars4.githubusercontent.com',
    'avatars5.githubusercontent.com', 'camo.githubusercontent.com',
    'central.github.com', 'cloud.githubusercontent.com', 'codeload.github.com',
    'collector.github.com', 'desktop.githubusercontent.com',
    'favicons.githubusercontent.com', 'gist.github.com',
    'github-cloud.s3.amazonaws.com', 'github-com.s3.amazonaws.com',
    'github-production-release-asset-2e65be.s3.amazonaws.com',
    'github-production-repository-file-5c1aeb.s3.amazonaws.com',
    'github-production-user-asset-6210df.s3.amazonaws.com', 'github.blog',
    'github.com', 'github.community', 'github.githubassets.com',
    'github.global.ssl.fastly.net', 'github.io', 'github.map.fastly.net',
    'githubstatus.com', 'live.github.com', 'media.githubusercontent.com',
    'objects.githubusercontent.com', 'pipelines.actions.githubusercontent.com',
    'raw.githubusercontent.com', 'user-images.githubusercontent.com',
    'vscode.dev', 'education.github.com', 'private-user-images.githubusercontent.com'
]

HOSTS_TEMPLATE = """# GitHub520 Host Start
{content}

# Update time: {update_time}
# Update url: https://raw.hellogithub.com/hosts
# Star me: https://github.com/521xueweihan/GitHub520
# GitHub520 Host End\n"""


@retry(tries=3)
def get_json(session: Any) -> Optional[list]:
    url = 'https://raw.hellogithub.com/hosts.json'
    try:
        rs = session.get(url)
        data = json.loads(rs.text)
        return data
    except Exception as ex:
        print(f"get: {url}, error: {ex}")
        raise Exception


def write_file(hosts_content: str, update_time: str) -> bool:
    output_doc_file_path = os.path.join(os.path.dirname(__file__), "README.md")
    template_path = os.path.join(os.path.dirname(__file__),
                                 "README_template.md")
    write_host_file(hosts_content)
    if os.path.exists(output_doc_file_path):
        with open(output_doc_file_path, "r") as old_readme_fb:
            old_content = old_readme_fb.read()
            if old_content:
                old_hosts = old_content.split("```bash")[1].split("```")[0].strip()
                old_hosts = old_hosts.split("# Update time:")[0].strip()
                hosts_content_hosts = hosts_content.split("# Update time:")[
                    0].strip()
                if old_hosts == hosts_content_hosts:
                    print("host not change")
                    return False

    with open(template_path, "r") as temp_fb:
        template_str = temp_fb.read()
        hosts_content = template_str.format(hosts_str=hosts_content,
                                            update_time=update_time)
        with open(output_doc_file_path, "w") as output_fb:
            output_fb.write(hosts_content)
    return True


def write_host_file(hosts_content: str) -> None:
    output_file_path = os.path.join(os.path.dirname(__file__), 'hosts')
    with open(output_file_path, "w") as output_fb:
        output_fb.write(hosts_content)


def write_json_file(hosts_list: list) -> None:
    output_file_path = os.path.join(os.path.dirname(__file__), 'hosts.json')
    with open(output_file_path, "w") as output_fb:
        json.dump(hosts_list, output_fb)


def write_hosts_content(content: str, content_list: list) -> str:
    if not content:
        return ""
    update_time = datetime.now(timezone.utc).astimezone(
        timezone(timedelta(hours=8))).replace(microsecond=0).isoformat()
    hosts_content = HOSTS_TEMPLATE.format(content=content,
                                          update_time=update_time)
    has_change = write_file(hosts_content, update_time)
    if has_change:
        write_json_file(content_list)
    return hosts_content


================================================
FILE: fetch_ips.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#   
#   Author  :   XueWeiHan
#   E-mail  :   595666367@qq.com
#   Date    :   2020-05-19 15:27
#   Desc    :   获取最新的 GitHub 相关域名对应 IP
import re
from typing import Any, Dict, List, Optional
from datetime import datetime
import sys
import asyncio
import aiodns

from pythonping import ping
from requests_html import HTMLSession
from retry import retry

from common import GITHUB_URLS, write_hosts_content


PING_TIMEOUT_SEC: int = 1
DISCARD_LIST: List[str] = ["1.0.1.1", "1.2.1.1", "127.0.0.1"]


PING_LIST: Dict[str, int] = dict()


def ping_cached(ip: str) -> int:
    global PING_LIST
    if ip in PING_LIST:
        return PING_LIST[ip]
    ping_times = [ping(ip, timeout=PING_TIMEOUT_SEC).rtt_avg_ms for _ in range(3)]
    ping_times.sort()
    print(f'Ping {ip}: {ping_times} ms')
    PING_LIST[ip] = ping_times[1] # 取中位数
    return PING_LIST[ip]


def select_ip_from_list(ip_list: List[str]) -> Optional[str]:
    if len(ip_list) == 0:
        return None
    ping_results = [(ip, ping_cached(ip)) for ip in ip_list]
    ping_results.sort(key=lambda x: x[1])
    best_ip = ping_results[0][0]
    print(f"{ping_results}, selected {best_ip}")
    return best_ip


@retry(tries=3)
def get_ip_list_from_ipaddress_com(session: Any, github_url: str) -> Optional[List[str]]:
    url = f'https://sites.ipaddress.com/{github_url}'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'
                      ' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/1'
                      '06.0.0.0 Safari/537.36'}
    try:
        rs = session.get(url, headers=headers, timeout=5)
        pattern = r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b"
        ip_list = re.findall(pattern, rs.html.text)
        return ip_list
    except Exception as ex:
        print(f"get: {url}, error: {ex}")
        raise Exception


DNS_SERVER_LIST = [
    "1.1.1.1",  # Cloudflare
    "8.8.8.8",  # Google
    "101.101.101.101",  # Quad101
    "101.102.103.104",  # Quad101
]


def windows_compatibility_check():
    if sys.platform == "win32":
        # 检查 pycares 是否正常加载
        try:
            import pycares
        except ImportError:
            raise RuntimeError("请先执行 'pip install pycares'")


async def get_ip_list_from_dns(
    domain,
    record_type="A",
    dns_server_list=["1.2.4.8", "114.114.114.114"],
):
    # Windows 兼容性检查
    windows_compatibility_check()

    # 配置 DNS 服务器
    resolver = aiodns.DNSResolver()
    resolver.nameservers = dns_server_list

    try:
        # 执行异步查询
        result = await resolver.query(domain, record_type)
        return [answer.host for answer in result]
    except aiodns.error.DNSError as e:
        print(f"{domain}: DNS 查询失败: {e}")
        return []


async def get_ip(session: Any, github_url: str) -> Optional[str]:
    ip_list_web = []
    try:
        ip_list_web = get_ip_list_from_ipaddress_com(session, github_url)
    except Exception as ex:
        pass
    ip_list_dns = []
    try:
        ip_list_dns = await get_ip_list_from_dns(github_url, dns_server_list=DNS_SERVER_LIST)
    except Exception as ex:
        pass
    ip_list_set = set(ip_list_web + ip_list_dns)
    for discard_ip in DISCARD_LIST:
        ip_list_set.discard(discard_ip)
    ip_list = list(ip_list_set)
    ip_list.sort()
    if len(ip_list) == 0:
        return None
    print(f"{github_url}: {ip_list}")
    best_ip = select_ip_from_list(ip_list)
    return best_ip


async def main() -> None:
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print(f'{current_time} - Start script.')
    session = HTMLSession()
    content = ""
    content_list = []
    for index, github_url in enumerate(GITHUB_URLS):
        print(f'Start Processing url: {index + 1}/{len(GITHUB_URLS)}, {github_url}')
        try:
            ip = await get_ip(session, github_url)
            if ip is None:
                print(f"{github_url}: IP Not Found")
                ip = "# IP Address Not Found"
            content += ip.ljust(30) + github_url
            global PING_LIST
            if PING_LIST.get(ip) is not None and PING_LIST.get(ip) == PING_TIMEOUT_SEC * 1000:
                content += "  # Timeout"
            content += "\n"
            content_list.append((ip, github_url,))
        except Exception:
            continue

    write_hosts_content(content, content_list)
    # print(hosts_content)
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print(f'{current_time} - End script.')


if __name__ == "__main__":
    if sys.platform == "win32":
        # Windows 事件循环策略配置
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    asyncio.run(main())

================================================
FILE: hosts
================================================
# GitHub520 Host Start
140.82.113.25                 alive.github.com
20.205.243.168                api.github.com
140.82.114.22                 api.individual.githubcopilot.com
185.199.110.133               avatars.githubusercontent.com
185.199.110.133               avatars0.githubusercontent.com
185.199.110.133               avatars1.githubusercontent.com
185.199.110.133               avatars2.githubusercontent.com
185.199.110.133               avatars3.githubusercontent.com
185.199.110.133               avatars4.githubusercontent.com
185.199.110.133               avatars5.githubusercontent.com
185.199.110.133               camo.githubusercontent.com
140.82.112.21                 central.github.com
185.199.110.133               cloud.githubusercontent.com
20.205.243.165                codeload.github.com
140.82.114.21                 collector.github.com
185.199.110.133               desktop.githubusercontent.com
185.199.110.133               favicons.githubusercontent.com
140.82.112.3                  gist.github.com
52.217.75.116                 github-cloud.s3.amazonaws.com
52.217.119.65                 github-com.s3.amazonaws.com
16.15.193.93                  github-production-release-asset-2e65be.s3.amazonaws.com
54.231.232.73                 github-production-repository-file-5c1aeb.s3.amazonaws.com
52.217.226.249                github-production-user-asset-6210df.s3.amazonaws.com
192.0.66.2                    github.blog
20.205.243.166                github.com
140.82.114.17                 github.community
185.199.108.154               github.githubassets.com
151.101.193.194               github.global.ssl.fastly.net
185.199.111.153               github.io
185.199.110.133               github.map.fastly.net
185.199.111.153               githubstatus.com
140.82.113.26                 live.github.com
185.199.110.133               media.githubusercontent.com
185.199.110.133               objects.githubusercontent.com
13.107.42.16                  pipelines.actions.githubusercontent.com
185.199.110.133               raw.githubusercontent.com
185.199.110.133               user-images.githubusercontent.com
13.107.213.73                 vscode.dev
140.82.112.22                 education.github.com
185.199.110.133               private-user-images.githubusercontent.com


# Update time: 2026-03-20T14:25:11+08:00
# Update url: https://raw.hellogithub.com/hosts
# Star me: https://github.com/521xueweihan/GitHub520
# GitHub520 Host End


================================================
FILE: hosts.json
================================================
[["140.82.113.25", "alive.github.com"], ["20.205.243.168", "api.github.com"], ["140.82.114.22", "api.individual.githubcopilot.com"], ["185.199.110.133", "avatars.githubusercontent.com"], ["185.199.110.133", "avatars0.githubusercontent.com"], ["185.199.110.133", "avatars1.githubusercontent.com"], ["185.199.110.133", "avatars2.githubusercontent.com"], ["185.199.110.133", "avatars3.githubusercontent.com"], ["185.199.110.133", "avatars4.githubusercontent.com"], ["185.199.110.133", "avatars5.githubusercontent.com"], ["185.199.110.133", "camo.githubusercontent.com"], ["140.82.112.21", "central.github.com"], ["185.199.110.133", "cloud.githubusercontent.com"], ["20.205.243.165", "codeload.github.com"], ["140.82.114.21", "collector.github.com"], ["185.199.110.133", "desktop.githubusercontent.com"], ["185.199.110.133", "favicons.githubusercontent.com"], ["140.82.112.3", "gist.github.com"], ["52.217.75.116", "github-cloud.s3.amazonaws.com"], ["52.217.119.65", "github-com.s3.amazonaws.com"], ["16.15.193.93", "github-production-release-asset-2e65be.s3.amazonaws.com"], ["54.231.232.73", "github-production-repository-file-5c1aeb.s3.amazonaws.com"], ["52.217.226.249", "github-production-user-asset-6210df.s3.amazonaws.com"], ["192.0.66.2", "github.blog"], ["20.205.243.166", "github.com"], ["140.82.114.17", "github.community"], ["185.199.108.154", "github.githubassets.com"], ["151.101.193.194", "github.global.ssl.fastly.net"], ["185.199.111.153", "github.io"], ["185.199.110.133", "github.map.fastly.net"], ["185.199.111.153", "githubstatus.com"], ["140.82.113.26", "live.github.com"], ["185.199.110.133", "media.githubusercontent.com"], ["185.199.110.133", "objects.githubusercontent.com"], ["13.107.42.16", "pipelines.actions.githubusercontent.com"], ["185.199.110.133", "raw.githubusercontent.com"], ["185.199.110.133", "user-images.githubusercontent.com"], ["13.107.213.73", "vscode.dev"], ["140.82.112.22", "education.github.com"], ["185.199.110.133", "private-user-images.githubusercontent.com"]]

================================================
FILE: requirements.txt
================================================
requests-html==0.10.0
pythonping==1.1.4
retry==0.9.2
lxml_html_clean
aiodns==3.0.0

================================================
FILE: update_ips.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
#   Author  :   XueWeiHan
#   E-mail  :   595666367@qq.com
#   Date    :   2025-01-16 15:27
#   Desc    :   GitHub Action 运行的脚本
import json
from typing import Any, Optional

from retry import retry
from requests_html import HTMLSession

from common import write_hosts_content


@retry(tries=3)
def get_json(session: Any) -> Optional[list]:
    url = 'https://raw.hellogithub.com/hosts.json'
    try:
        rs = session.get(url)
        data = json.loads(rs.text)
        return data
    except Exception as ex:
        print(f"get: {url}, error: {ex}")
        raise Exception


def main() -> None:
    print('Start script.')
    session = HTMLSession()
    content = ""
    content_list = get_json(session)
    for item in content_list:
        content += item[0].ljust(30) + item[1] + "\n"
    hosts_content = write_hosts_content(content, content_list)
    print(hosts_content)
    print('End script.')


if __name__ == '__main__':
    main()
Download .txt
gitextract_btmf6xsu/

├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── GitHub520.yml
├── .gitignore
├── README.md
├── README_template.md
├── actions_requirements.txt
├── common.py
├── fetch_ips.py
├── hosts
├── hosts.json
├── requirements.txt
└── update_ips.py
Download .txt
SYMBOL INDEX (14 symbols across 3 files)

FILE: common.py
  function get_json (line 46) | def get_json(session: Any) -> Optional[list]:
  function write_file (line 57) | def write_file(hosts_content: str, update_time: str) -> bool:
  function write_host_file (line 83) | def write_host_file(hosts_content: str) -> None:
  function write_json_file (line 89) | def write_json_file(hosts_list: list) -> None:
  function write_hosts_content (line 95) | def write_hosts_content(content: str, content_list: list) -> str:

FILE: fetch_ips.py
  function ping_cached (line 29) | def ping_cached(ip: str) -> int:
  function select_ip_from_list (line 40) | def select_ip_from_list(ip_list: List[str]) -> Optional[str]:
  function get_ip_list_from_ipaddress_com (line 51) | def get_ip_list_from_ipaddress_com(session: Any, github_url: str) -> Opt...
  function windows_compatibility_check (line 75) | def windows_compatibility_check():
  function get_ip_list_from_dns (line 84) | async def get_ip_list_from_dns(
  function get_ip (line 105) | async def get_ip(session: Any, github_url: str) -> Optional[str]:
  function main (line 128) | async def main() -> None:

FILE: update_ips.py
  function get_json (line 18) | def get_json(session: Any) -> Optional[list]:
  function main (line 29) | def main() -> None:
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (30K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 160,
    "preview": "# These are supported funding model platforms\n\ngithub: [521xueweihan]\ncustom: ['https://hellogithub.com/', 'https://mp.w"
  },
  {
    "path": ".github/workflows/GitHub520.yml",
    "chars": 1337,
    "preview": "# This workflow will install Python dependencies, run tests and lint with a variety of Python versions\n# For more inform"
  },
  {
    "path": ".gitignore",
    "chars": 1816,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
  },
  {
    "path": "README.md",
    "chars": 6458,
    "preview": "# GitHub520\n\n<p align=\"center\">\n<a href=\"https://hellogithub.com/repository/d05ff820bf36470581c02cda5cbd17ea\" target=\"_b"
  },
  {
    "path": "README_template.md",
    "chars": 3981,
    "preview": "# GitHub520\n\n<p align=\"center\">\n<a href=\"https://hellogithub.com/repository/d05ff820bf36470581c02cda5cbd17ea\" target=\"_b"
  },
  {
    "path": "actions_requirements.txt",
    "chars": 50,
    "preview": "requests-html==0.10.0\nretry==0.9.2\nlxml_html_clean"
  },
  {
    "path": "common.py",
    "chars": 4248,
    "preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n#\n#   Author  :   XueWeiHan\n#   E-mail  :   595666367@qq.com\n#   Date    : "
  },
  {
    "path": "fetch_ips.py",
    "chars": 4699,
    "preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n#   \n#   Author  :   XueWeiHan\n#   E-mail  :   595666367@qq.com\n#   Date   "
  },
  {
    "path": "hosts",
    "chars": 2476,
    "preview": "# GitHub520 Host Start\n140.82.113.25                 alive.github.com\n20.205.243.168                api.github.com\n140.8"
  },
  {
    "path": "hosts.json",
    "chars": 2008,
    "preview": "[[\"140.82.113.25\", \"alive.github.com\"], [\"20.205.243.168\", \"api.github.com\"], [\"140.82.114.22\", \"api.individual.githubco"
  },
  {
    "path": "requirements.txt",
    "chars": 82,
    "preview": "requests-html==0.10.0\npythonping==1.1.4\nretry==0.9.2\nlxml_html_clean\naiodns==3.0.0"
  },
  {
    "path": "update_ips.py",
    "chars": 994,
    "preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n#\n#   Author  :   XueWeiHan\n#   E-mail  :   595666367@qq.com\n#   Date    : "
  }
]

About this extraction

This page contains the full source code of the 521xueweihan/GitHub520 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (27.6 KB), approximately 9.0k tokens, and a symbol index with 14 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!