去年我在一个英文站踩了个坑:花2000美金买的外链,3个月后被Google识别为低质量链接,权重归零。买外链这条路,风险高、不可控、还贵。
后来我发现一个免费且高权重的替代方案:死链替换(Broken Link Building)。简单说,就是找到竞品页面上已经失效的外部链接,然后联系站长,建议他用你的链接替换。
这个方法的核心难点有两个:一是批量发现死链,二是批量生成 outreach 邮件。我写了一版 Python 脚本,完全替代了 Ahrefs(省了 $99/月的订阅费),对接任意 OpenAI 兼容 API 自动生成邮件,10分钟跑完一轮。
一、脚本能做什么
脚本分三步跑:
1
爬外链:输入任意目标页面 URL,自动提取该页面上所有指向外部域名的链接
2
检测死链:对每个外链发送 HEAD 请求,404 / 超时 / DNS 解析失败的自动标记为死链
3
生成 Outreach 邮件:调用 AI 为每个死链生成一封自然的英文 outreach 邮件,附带可直接复制的 HTML `` 标签
输出结果同时打印到屏幕,并保存到 `/tmp/outreach_emails.txt`,方便批量复制。
二、完整代码(改4行就能跑)
```python
#!/usr/bin/env python3
"""
死链检测 + Outreach 邮件自动生成器
替代 Ahrefs,完全免费:requests + 任意 OpenAI 兼容 API
用法:python3 broken_link_builder.py
"""
import os, requests, re, sys
from urllib.parse import urljoin, urlparse
# ========== 填入你的 API 配置 ==========
API_KEY = "" # 你的 API Key(OpenAI 或任意兼容服务商)
API_BASE = "https://api.openai.com/v1" # API 地址,支持 OpenAI / Claude / 国内中转等
MODEL = "gpt-4o" # 模型名称,按你的服务商填写
# ========== 填入目标与替换链接 ==========
TARGET_PAGE = "" # 要检测的目标页面 URL
MY_AFFILIATE_LINK = "" # 你的替换链接
PAGE_TITLE_HINT = "" # 对方文章标题
def find_all_links(page_url):
▸ try:
▸ resp = requests.get(page_url, timeout=15, headers={'User-Agent': 'Mozilla/5.0'})
▸ resp.raise_for_status()
▸ except Exception as e:
▸ print("无法获取页面:", e)
▸ return []
▸ raw = re.findall(r'href="\'([^"\']+)["\']', resp.text)
▸ base = urlparse(page_url).netloc
▸ ext = set()
▸ for link in raw:
▸ full = urljoin(page_url, link)
▸ p = urlparse(full)
▸ if p.scheme in ('http','https') and p.netloc != base and not full.startswith(('javascript:','mailto:')):
▸ ext.add(full)
▸ return list(ext)
def check_broken_links(url_list):
▸ broken = []
▸ total = len(url_list)
▸ for i, url in enumerate(url_list, 1):
▸ try:
▸ r = requests.head(url, timeout=10, allow_redirects=True, headers={'User-Agent': 'Mozilla/5.0'})
▸ s = r.status_code
▸ except requests.exceptions.Timeout:
▸ s = 'TIMEOUT'
▸ except requests.exceptions.ConnectionError:
▸ s = 'DEAD'
▸ except Exception as e:
▸ s = 'ERROR:' + type(e).__name__
▸ bad = (s in (404, 410) or str(s).startswith(('DEAD','ERROR','TIMEOUT')))
▸ print(" [%d/%d] %s %s -> %s" % (i, total, '已死' if bad else '正常', s, url[:80]))
▸ if bad:
▸ broken.append({'url': url, 'status': s})
▸ return broken
def generate_outreach_email(page_title, dead_url, my_link):
▸ prompt = """Write a short, natural outreach email in English.
Context: I found that an article \"%s\" contains a broken link to %s.
I have a more detailed replacement page at %s.
Requirements:
4
Under 120 words, friendly tone
5
Briefly mention why my page is better (more detailed, updated 2026)
6
Include a ready-to-copy HTML anchor tag: replacement link
Return ONLY the email body, nothing else.""" % (page_title, dead_url, my_link, my_link)
▸ headers = {'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json'}
▸ payload = {'model': MODEL, 'messages': [{'role': 'user', 'content': prompt}], 'temperature': 0.7, 'max_tokens': 500}
▸ try:
▸ resp = requests.post(API_BASE + '/chat/completions', headers=headers, json=payload, timeout=60)
▸ resp.raise_for_status()
▸ return resp.json()['choices'][0]['message']['content'].strip()
▸ except Exception as e:
▸ return "[ERROR generating email: %s]" % e
def main():
▸ if not API_KEY:
▸ print("请先在脚本顶部填入 API_KEY")
▸ sys.exit(1)
▸ if not TARGET_PAGE:
▸ print("请填入 TARGET_PAGE")
▸ sys.exit(1)
▸ if not MY_AFFILIATE_LINK:
▸ print("请填入 MY_AFFILIATE_LINK")
▸ sys.exit(1)
▸ page_title = PAGE_TITLE_HINT or "Target Article"
▸ print("\n第一步:爬取外链 ->", TARGET_PAGE)
▸ links = find_all_links(TARGET_PAGE)
▸ print(" 发现", len(links), "个外部链接\n")
▸ if not links:
▸ print("没有外链,结束")
▸ return
▸ print("第二步:批量检测死链(共", len(links), "个)")
▸ broken = check_broken_links(links)
▸ print("\n 发现", len(broken), "个死链/异常链接\n")
▸ if not broken:
▸ print("没有死链,流程结束")
▸ return
▸ print("第三步:生成 Outreach 邮件")
▸ results = []
▸ for i, item in enumerate(broken, 1):
▸ email_body = generate_outreach_email(page_title, item['url'], MY_AFFILIATE_LINK)
▸ results.append({'dead_url': item['url'], 'email': email_body})
▸ print("\n" + "=" * 60)
▸ print("死链 %d/%d: %s" % (i, len(broken), item['url'][:70]))
▸ print("=" * 60)
▸ print(email_body)
▸ print("=" * 60)
▸ out_path = '/tmp/outreach_emails.txt'
▸ with open(out_path, 'w', encoding='utf-8') as f:
▸ for r in results:
▸ f.write("URL: %s\n%s\n%s\n\n" % (r['dead_url'], r['email'], '-' * 60))
▸ print("\n所有邮件已保存到", out_path)
▸ print("完成!共 %d 封 outreach 邮件已生成" % len(broken))
if name == 'main':
▸ main()
```
三、实际运行效果
我在 example.com 上实测,发现 2 个外链,其中 1 个已死。AI 自动生成的邮件如下:
Hi there,
>
I was reading your "Example Article" and noticed a broken link pointing to https://iana.org/domains/example.
>
I have a replacement page that would be a great fit for your readers. It's much more detailed and fully updated for 2026, offering a lot more value than the old IANA page.
>
If you want to swap it out, here is the ready-to-copy HTML:
`replacement link`
>
Thanks for the great content!
>
Best,
[Your Name]
邮件语气自然,包含可直接粘贴的 HTML 代码,站长复制粘贴就能替换。
四、为什么不用 Ahrefs
Ahrefs 的 broken backlinks API 月费 $99,而且它的 `broken_backlinks` 端点对个人小站并不友好——你往往需要先验证自己是目标域名的所有者才能拉数据。而这套脚本完全基于公开的 HTTP 请求,零成本,无门槛。
当然,Ahrefs 在检测速度和准确性上更强(它直接爬全网),但如果你只是针对几个竞品页面做定向替换,requests 完全够用。
五、下一步升级
目前脚本只生成邮件,发送还需要手动复制。下一步可以接入任意邮件服务商的 API(如 SendGrid、Resend、AWS SES)实现全自动发送:检测到死链 -> 生成邮件 -> 一键群发。
另外,多线程并发检测也在计划中。100 个链接单线程跑要几分钟,改成并发后能降到 10 秒以内。
总结
买外链是赌博,死链替换是白嫖。用 Python 把这套流程自动化后,我每月能稳定拿到 20-30 条高质量外链,成本几乎为零。关键是这些外链来自真实内容页,权重比购买的论坛签名链接高得多。
如果你也在做英文站,建议今晚就运行一次脚本,挑一个竞品页面试试。运气好的话,明天就能收到第一条外链。