A8DOG

A8DOG

随便写写,记录折腾过程!
telegram

WordPress搭配WP Super Cache + Python脚本实现暴力预缓存 全站静态化

WordPress 有定时任务机制,WP Super Cache 插件就是通过这个定时任务来进行预缓存,在我使用的过程中预缓存一次最多生成十几个页面,并且在下一次定时任务运行的时候才会继续生成,效率是非常的慢,如果一直挂着 WP Super Cache 预缓存页面可以一直自动生成,但是效率还是太慢了,于是我写了一个简单的 python 脚本并且可以把 WP Super Cache 不能预缓存的分类页面也能缓存上。

https://img.a8dog.com/i/2024/03/25/qw5iaj.png

代码:#

首先我们的服务器需要 python3 环境,并且我们的 WordPress 安装好了 WP Super Cache 插件,把下面的代码编辑成 page.py,用于缓存分类的分页。

import os
import requests
import time
from concurrent.futures import ThreadPoolExecutor
from itertools import islice

# 定义链接和对应的数量
links = {
    "https://a8dog.com": 60,
    "https://a8dog.com/a8": 10,
}

# 生成链接
all_links = []
for link, count in links.items():
    for i in range(1, count + 1):
        page_link = f"{link}/page/{i}" if i > 1 else link
        all_links.append(page_link)

# 将链接分组以便后续并发访问
def chunk(it, size):
    it = iter(it)
    return iter(lambda: tuple(islice(it, size)), ())

# 访问链接的函数
def visit_url(url):
    try:
        response = requests.get(url)
        print(f"Visited: {url}, Status Code: {response.status_code}")
    except Exception as e:
        print(f"Failed to visit: {url}, Error: {e}")

# 设置并发数和延迟
concurrency = 10  # 并发数
delay = 1  # 延迟时间(秒)

# 创建线程池并并发访问链接
with ThreadPoolExecutor(max_workers=concurrency) as executor:
    for chunked_links in chunk(all_links, concurrency):
        futures = [executor.submit(visit_url, url) for url in chunked_links]
        time.sleep(delay)

# 将链接写入到page.txt文件中
with open("page.txt", "w") as f:
    for link in all_links:
        f.write(link + "\n")

把代码中的链接替换成你的分类页就可以了,每一行的分类页后面数字就是你的分页数量。

比如我的分类有 10 页,那么我可以设置 15 页,后续文章多了分页多了不会缓存不上。

在把下面的代码添加到 url.py:

import requests
import xml.etree.ElementTree as ET
import threading
import time

# 设置并发数和请求间隔
CONCURRENT_REQUESTS = 10
REQUEST_INTERVAL = 1  # seconds

def fetch_sitemap(url):
    """
    获取网站地图内容
    """
    response = requests.get(url)
    if response.status_code == 200:
        return response.content
    else:
        print(f"Failed to fetch sitemap from {url}")
        return None

def extract_sitemap_urls(sitemap_content):
    """
    从网站地图内容中提取子地图链接
    """
    urls = []
    if sitemap_content:
        try:
            root = ET.fromstring(sitemap_content)
            for loc in root.findall(".//{http://www.sitemaps.org/schemas/sitemap/0.9}loc"):
                urls.append(loc.text)
        except ET.ParseError as e:
            print("Error parsing sitemap XML:", e)
    return urls

def fetch_urls_from_sitemap(url):
    """
    从网站地图中提取网页链接
    """
    sitemap_content = fetch_sitemap(url)
    if sitemap_content:
        return extract_sitemap_urls(sitemap_content)
    else:
        return []

def fetch_url(url):
    """
    发送请求到网站链接
    """
    try:
        response = requests.get(url)
        # 在这里处理你想要的响应内容
        print("Fetched:", url)
    except requests.RequestException as e:
        print("Error fetching", url, ":", e)

def main():
    sitemap_url = "https://a8dog.com/wp-sitemap.xml"  # 替换为你的网站地图链接
    sitemap_urls = fetch_urls_from_sitemap(sitemap_url)
    all_urls = []

    # 从所有子地图中提取网页链接
    for url in sitemap_urls:
        all_urls.extend(fetch_urls_from_sitemap(url))

    # 写入到url.txt文件
    with open('url.txt', 'w') as f:
        for url in all_urls:
            f.write(url + '\n')
    print("Urls extracted and written to url.txt file.")

    # 并发请求的线程函数
    def fetch_urls(urls):
        while urls:
            url = urls.pop(0)
            fetch_url(url)
            time.sleep(REQUEST_INTERVAL)

    # 以CONCURRENT_REQUESTS个线程并发发送请求
    threads = []
    for _ in range(CONCURRENT_REQUESTS):
        thread = threading.Thread(target=fetch_urls, args=(all_urls,))
        thread.start()
        threads.append(thread)

    # 等待所有线程完成
    for thread in threads:
        thread.join()

if __name__ == "__main__":
    main()

把地图地址替换成你的地图地址,会自动抓取网站的全部链接进行预缓存。

如果我们在宝塔添加定时任务选择 shell 脚本:

python3 /你的目录/page.py
python3 /你的目录/url.py

可能会出现一个报错:

Traceback (most recent call last):
  File "/a8dog.py", line 2, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'

这是因为宝塔的定时任务是使用宝塔的 python 环境,没有安装 requests 模块,我们只需要随便添加一个 shell 定时任务脚本:

pip3 install requests

执行一下,然后再重新添加定时任务就可以了。

注意:#

如果你的域名有 cdn 或者防火墙,频繁的预缓存可能会出现被拦截的情况,请把 IP 加入白名单 并且把修改 host 文件,把域名指向源 IP 或者 127.0.0.1,这样就不会消耗 cdn 流量。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。