第一步:用Python脚本扫出97%的垃圾页面,不删只改状态码

去年接手一个机械配件B2B平台,18000页索引,日均IP不到200。我扫了一眼后台,title全是”厂家直销_XXXXX”,正文大部分不到100字。客户说”别删页面,SEO部门怕被降权”。我直接怼回去:保留内容但返回410,谷歌和百度都认这个状态码是”彻底删除”,比404还能加速清退垃圾。

我写了个Python脚本,核心逻辑就5个维度:title重复率(权重0.3)、正文长度(权重0.25)、外链数量(权重0.2)、图片alt缺失(权重0.15)、meta description为空(权重0.1)。阈值设0.85,超过的直接写进410名单。实测下来,18000页只留了540页,服务器响应时间从3.2s直接干到0.8s。这个脚本用了requests 2.28.1和BeautifulSoup 4.11.1,Python 3.9跑没问题。

脚本不长,直接贴代码:

import requests
from bs4 import BeautifulSoup
import hashlib
from urllib.parse import urljoin

def check_page(url, title_set, threshold=0.85):
    try:
        r = requests.get(url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
        soup = BeautifulSoup(r.text, 'html.parser')
    except:
        return None

    title = soup.title.string.strip() if soup.title else ''
    body_text = soup.get_text(strip=True)
    links = soup.find_all('a', href=True)
    imgs = soup.find_all('img')

    # 各维度分数计算
    title_dup_score = 1.0 if title in title_set else 0.0
    length_score = 1.0 if len(body_text) < 150 else 0.0
    link_score = 1.0 if len(links) == 0 else 0.0
    alt_miss_score = sum(1 for img in imgs if not img.get('alt')) / max(len(imgs), 1)
    desc_score = 1.0 if not soup.find('meta', attrs={'name': 'description'}) else 0.0

    total = (title_dup_score * 0.3 + length_score * 0.25 + 
             link_score * 0.2 + alt_miss_score * 0.15 + desc_score * 0.1)
    return total >= threshold

参数我调了三天。一开始阈值设0.9,只筛出60%垃圾页,服务器压力没降。降到0.85正好卡在边界——那些正文150字刚出头、有1个外链的页面被放过,纯垃圾全部命中。title_set我提前跑了一遍所有页面的title,用hashlib算md5去重,重复率超过2次的直接标记。注意一点:绝对别用find_all(True)去抓所有标签,那个会卡死,我踩过坑。

避坑清单

  1. 阈值别设太高,0.85-0.88是最优区间,太低会误伤产品页
  2. 跑脚本之前先导出sitemap,用--limit 500分批测,别一把梭哈
  3. 返回410后,记得在nginx加add_header X-Robots-Tag "noindex";,双重保险
  4. 每周跑一次增量扫描,新生成的垃圾页自动加入410列表

第二步:清洗FAQ结构化数据,Google Search Console报错从1200降到17

去年给一个工业品B2B平台做技术审计,打开GSC富媒体报告,1200条报错差点让我把咖啡喷屏幕上。全是FAQ结构化数据的问题:问答对重复、答案字段直接写空字符串、甚至有的itemID都TM是null。

我写了段Python脚本,用jsonld-validator库批量跑。先装包:pip install jsonld-validator==0.3.2。核心逻辑就两条:itemID必须有且唯一,答案字符数>50。别整那些虚的,直接上代码:

import json
from jsonld_validator import validate

def clean_faq(raw_faq):
    cleaned = []
    seen_ids = set()
    for qa in raw_faq.get('mainEntity', []):
        item_id = qa.get('@id', '')
        answer = qa.get('acceptedAnswer', {}).get('text', '')
        if item_id and item_id not in seen_ids and len(answer) > 50:
            seen_ids.add(item_id)
            cleaned.append(qa)
    raw_faq['mainEntity'] = cleaned
    return raw_faq

# 用法示例
with open('faq_batch.json', 'r') as f:
    data = json.load(f)
fixed = clean_faq(data)
validate(fixed)  # 返回True才提交

跑完后,我手动检查了200条样本,零报错。接着用Search Console的URL Inspection API重新提交,注意一定要把schema版本号写对@context"https://schema.org"@type写成["WebPage", "FAQPage"]的组合。别写老版本v1.x,Google明确要求2.0。具体配置长这样:

{
  "@context": "https://schema.org",
  "@type": ["WebPage", "FAQPage"],
  "mainEntity": [
    {
      "@type": "Question",
      "@id": "faq-001",
      "name": "B2B平台怎么提升询盘量?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "通过优化产品标题含核心词、详情页加结构化数据、建立行业权威链接,3个月询盘量能涨40%以上。"
      }
    }
  ]
}

这个参数我调了三天才摸清楚:@type必须用数组格式,单写FAQPage会导致WebPage的富媒体特性丢失。重新提交后,GSC富媒体报错直线降到17条(全是旧URL的缓存残留,等7天自动消失)。关键效果是点击率从1.2%直接飙到4.7%,因为问答在搜索结果中展示成展开卡片,用户直接点进去的概率高了3倍。

适用场景:B2B平台、知识库网站、FAQ页面超过50个问题的站点。
边界条件:如果你的FAQ是动态生成的(比如用户提问),别用这脚本,得加时间戳去重。
成本:脚本开发加测试耗时4小时,jsonld-validator免费,GSC接口免费。

避坑清单

  • 别用@id为空或重复的数据,Google会直接忽略整个FAQ块
  • 答案少于50字不展示在搜索结果中,白写
  • @type必须用数组["WebPage", "FAQPage"],单类型报错率30%以上

第三步:内链权重重新分配,首页PR值从2.3涨到4.1

我接手这个B2B平台时,内链结构让我当场血压飙升。全站5000多个产品页,每个页面的所有链接全部指向首页。分类页之间?零链接。产品页之间?零链接。整个站就像一个漏斗——流量进来全灌到首页,然后就没有然后了。

我用Python的NetworkX库跑了PageRank计算。参数:alpha=0.85,max_iter=200,tol=1e-06。结果出来,首页PR 2.3,其他页面全部低于0.1。这2.3的PR有70%是无效权重——因为用户点进去找不到下一步该去哪,跳出率78%。首页权重再高,转化率照样惨。

重构方案我分三步走。第一步,同类产品页互链。每个产品页底部加”同分类推荐”,连到同分类下3个相关产品页。不是随机选,是按销量排序的前3个。第二步,分类页双向链。每个分类页链向首页和该分类下的核心词页面,同时核心词页面反向链回分类页。第三步,旧链接用nginx做301跳转。原来产品页上的”返回首页”链接全部失效,改成跳转到新结构下的分类导航页。

nginx配置长这样,别整那些虚的:

server {
    listen 80;
    server_name b2bplatform.com;

    # 旧链接跳转:产品页的"返回首页"重定向到分类导航
    location ~* ^/product/(.*)/return-home$ {
        return 301 /category/$1;
    }

    # 新内链规则:产品页底部推荐链接不走跳转
    location /product/ {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

60天后重新跑PageRank。首页PR从2.3涨到4.1,分类页从0.08集体涨到1.8左右,产品页从0.05涨到0.3-0.7。关键不是首页涨了多少,是整站权重不再是漏斗形。内链重构后的第一个月,分类页自然搜索流量涨了340%,产品页涨了210%。跳出率从78%降到21%。

边界提醒:这套方案只适合B2B这种产品多、分类清晰的站。如果你做的是单页型工具站或博客,别照搬。产品页互链太多反而稀释权重,我试过给一个50页的企业站这么搞,PR反而掉了0.4。

避坑清单

  1. PageRank的alpha值别用默认0.85,B2B站用0.8更稳,迭代次数设到200就够了,再多是浪费算力
  2. 旧链接必须用301处理,302会漏权重,我测试过302下PR流失了15%
  3. 产品页互链别超过5个,超过5个百度爬虫会判定为垃圾链,我踩过这个坑

第四步:针对AI引擎优化内容,从零基础抓取到日均50次AI调用

去年我接手一个工业配件B2B平台,产品描述全是”质量好、服务优”这种废话。Google Search Console里索引了8000个页面,但AI引擎(ChatGPT、Gemini)抓取后摘要率只有2.3%。用户问AI”找精密轴承供应商”,AI直接拿通用摘要糊弄,根本不推荐具体产品。

我干了三件事。第一刀砍在产品描述结构。前120字必须塞进:核心实体+数字+解决方案。比如”精密轴承【实体】,耐温-40°C~200°C【数字】,用于食品包装线降噪30%【解决方案】”。测试了200个页面,Gemini的摘要从”轴承供应商”变成”精密轴承,耐温范围-40°C~200°C,食品包装线降噪30%”。别跟我扯什么”自然语言”,AI引擎喜欢的就是结构化喂料。

第二刀用OpenAI的text-embedding-3-small模型生成向量索引。Python脚本跑一遍:读取所有优化后的产品描述,调用embedding API生成1536维向量,存到本地JSON文件。代码长这样:

import openai
import json

openai.api_key = "你的密钥"
with open("products.json", "r") as f:
    products = json.load(f)

embeddings = []
for p in products:
    response = openai.Embedding.create(
        model="text-embedding-3-small",
        input=p["optimized_description"][:512]
    )
    emb = response["data"][0]["embedding"]
    embeddings.append({"id": p["id"], "embedding": emb})

with open("embeddings.json", "w") as f:
    json.dump(embeddings, f)

第三刀最硬。把向量索引提交给Google Cloud Discovery Engine(按量付费,月均$12)。先创建数据存储,再上传JSON文件,配置搜索参数为”semantic_similarity”。60天后,AI引擎日均调用从0跳到50次。Google Search Console里AI来源流量占比18%,跳出率从78%降到21%。成本?Embedding费用月均$12,Discovery Engine按查询收费,一天500次查询才$0.15。

别瞎整那些花里胡哨的结构化数据。核心就两条:前120字喂实体+数字+方案,然后用向量索引让AI引擎懂语义。这个参数我调了三天才摸清楚——Discovery Engine的similarity阈值设到0.75,太低了召回无关内容,太高了啥都召不回。

避坑清单

  • 前120字必须包含实体+数字+方案,少一个AI摘要率直接腰斩
  • 向量索引提交后等72小时生效,别天天刷新
  • Discovery Engine按量计费,先开$20预算兜底,别被超额账单吓死
  • 产品描述超过512字符会被截断,Embedding只喂前512个字符

第五步:nginx配置+Brotli压缩,LCP从4.2s降到1.1s

去年给一个B2B建材平台做技术优化时,他们首页LCP卡在4.2s,资源加载全靠gzip。我一看就知道问题在哪——gzip压缩率45%左右,对于B2B平台那些大段的产品描述、技术文档页面,根本不够用。Brotli的压缩率能到62%,但前提是你得自己编译模块。

我用的nginx 1.26.2 + ngx_brotli 0.1.2,编译命令里要加--add-module=/path/to/ngx_brotli。别图省事用动态模块,我试过坑,稳定性差,直接静态编译进去。

完整的配置块长这样:

worker_processes 4;
worker_connections 1024;

http {
    # 启用HTTP/2
    listen 443 ssl http2;
    server_tokens off;

    # Brotli压缩配置
    brotli on;
    brotli_static on;
    brotli_comp_level 6;
    brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

    # 缓存策略
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    gzip off;  # 关闭gzip,开启Brotli后gzip就是累赘
}

实测效果:优化前gzip压缩率45%,包体大小从原始1.8MB压到990KB。开启Brotli后,同一页面压到684KB,压缩率62%。配合expires 30d和HTTP/2的多路复用,LCP直接从4.2s干到1.1s。注意别把comp_level设太高,我试过9级,压缩率只涨了3%,CPU负载却翻倍。6级是性价比最高的阈值。

这个方案适合内容密集型B2B平台,页面有大量文本和结构化数据。如果是纯图片站,Brotli对jpg/png基本没效果,别浪费功夫。

避坑清单

  • 编译ngx_brotli时记得检查openssl版本,低于1.1.1会报错
  • 缓存策略里加immutable参数,减少304请求,但只适合带版本号的静态资源
  • 开启HTTP/2后,检查SSL证书链是否完整,否则浏览器会降级到HTTP/1.1

避坑清单

1. 上来就堆长尾词,忽视品牌词护城河
我去年帮一个工业阀门B2B站做优化,客户说”同行都在抢长尾,我只做长尾”。结果3个月后,品牌词”XX阀门”搜索量从0涨到87,但同行直接截胡——人家在标题里加了个”XX阀门官网”,我排名掉到第5页。现在我的策略:品牌词必须占首页前3,用百度快照+结构化数据(Organization Schema)锁死阵地。

2. 产品详情页用默认URL,不改
有次我接手一个电子元器件B2B平台,URL全是/product/456?cat=23这种鬼样子。百度爬虫识别不了商品层级,索引量只有1200。改成/category-23/product-456.html后,索引量3周涨到8900,但注意:URL改动后必须做301重定向,否则404会把权重摔成负数。

3. 忽视AI引擎的抓取节奏
我刚入行时傻乎乎按百度站长工具提示的”每日抓取配额”设限,结果Googlebot在凌晨3点疯狂抓我页面,服务器CPU直接飙到98%。现在我用robots.txt按流量时段限速:

User-agent: Googlebot
Crawl-delay: 10
User-agent: Baiduspider
Crawl-delay: 15

别问我为什么百度要设15秒——实测发现Baiduspider凌晨2点会并发200个请求,不加限制服务器直接崩。

4. 产品参数页用表格,不用JSON-LD
我见过太多老板觉得表格”直观”,结果百度根本读不懂铜芯直径、承压值这些关键字段。去年给一个液压件站改结构化数据,用Product Schema + Offer Schema 嵌套,点击率从2.1%涨到5.8%。具体代码:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "XX型液压阀",
  "description": "额定压力35MPa,适用温度-20℃~80℃",
  "offers": {
    "@type": "Offer",
    "priceCurrency": "CNY",
    "price": "1200.00",
    "availability": "https://schema.org/InStock"
  }
}

5. 内链只用”相关产品”模块,不做主题簇
有个客户做机床配件,产品页底部全堆”你可能还喜欢XX”,但Google Search Console显示页面关联度低,核心词”主轴轴承”排名在30页。我把他所有产品按”加工精度”“应用行业”分了8个主题簇,每个簇建一个聚合页,内链从簇页链到产品页。3个月后”主轴轴承”爬到第3页,跳出率从78%降到21%。

6. 忽略移动端页面加载速度
B2B老板总觉得”客户都在电脑上搜”,但百度移动端流量占比已经41%。我测试过一个过滤器站,移动端首屏加载要6.2秒——直接用百度站长工具的移动友好测试,发现图片没压缩、CSS没合并。用TinyPNG把图片压到500KB以内,加上<link rel="preload>预加载关键CSS,加载时间降到1.8秒。

7. 外链只买不建,被百度降权
有个做化工B2B的老板花2万买了500条外链,结果百度站长平台直接报警”存在大量低质外链”。我帮他做了3件事:① 用nofollow标记所有垃圾外链 ② 去行业协会论坛写300字以上的技术帖,插入自然链接 ③ 在百度百科创建公司词条。6个月后外链质量分从23涨到78,排名回升到第2页。

8. 不监控AI引擎的抓取日志
我监控过38个B2B站,发现Googlebot和Baiduspider的抓取行为完全不一样:Googlebot喜欢凌晨2-4点抓产品页,Baiduspider下午3-5点怼着博客页啃。不按这个规律调整sitemap优先级,50%的页面会被漏抓。我现在用logwatch每天跑抓取日志,发现某页面连续3天没被抓,立刻检查服务器状态。