K7

K7Blog

须知少年凌云志 曾许人间第一流.
proton
telegram

WordPress搭配WP Super Cache + Python腳本實現暴力預快取 全站靜態化

WordPress 有定時任務機制,WP Super Cache 插件就是通過這個定時任務來進行預緩存,在我使用的過程中預緩存一次最多生成十幾個頁面,並且在下一次定時任務運行的時候才會繼續生成,效率是非常的慢,如果一直掛著 WP Super Cache 預緩存頁面可以一直自動生成,但是效率還是太慢了,於是我寫了一個簡單的 python 腳本並且可以把 WP Super Cache 不能預緩存的分類頁面也能緩存上。

https://img.k7blog.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://k7blog.com": 60,
    "https://k7blog.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://k7blog.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 流量。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。