2026年用Python检测移动端适配SEO问题:一键扫出“手机上打不开/排版乱“的页面

目录

  • 引言
  • 核心概念
  • 代码示例
  • 总结

2026年用Python检测移动端适配SEO问题:一键扫出"手机上打不开/排版乱"的页面

谷歌从 2019 年起就是移动优先索引(mobile-first indexing):它用手机版判断排名,不是桌面版。

你的网站桌面端再漂亮,手机端如果字体小到看不清、按钮点不准、还要左右横滑——谷歌直接给你降权。

本文给一套可运行的 Python 工具,批量扫出全站移动端适配问题,附修复建议和超链接。


一、为什么 2026 年还得死磕移动端

  • 移动优先索引已全覆盖:谷歌主要用移动版内容做抓取、索引和排名。
  • 移动端 Core Web Vitals 是硬指标:LCP / INP / CLS 以移动端真实字段数据(CrUX p75)为准,桌面过了没用。
  • 移动友好测试工具已下线(2024 年后),官方现在让你用GSC 移动易用性报告 + PageSpeed Insights自查——但这两个都只能逐页看,没法批量扫全站。

所以自己写脚本批量扫

,是独立站/SEO 团队的必备动作。


二、移动端适配到底查什么(Google 历史判分维度)

检查项问题表现后果
viewport 配置缺width=device-width手机按桌面宽度渲染,字小需缩放
字号过小< 12px(或过小固定值)可读性差,易判移动不友好
点击目标太小/太密按钮 < 48×48 CSS px 或间距不足误触,体验差
横向溢出内容宽于视口,需横滑直接判定"内容不适配"
插件依赖Flash / 旧 object移动端无法运行
错误移动跳转rel=alternate media=only screen配错手机用户被导到错误页
图片尺寸缺失无 width/height/srcset布局抖动(CLS↑)

三、工具:mobile_seo_checker.py

纯requests + bs4

,无需 API key,本地即跑。静态层能覆盖 80% 问题;需要真实布局测量(字号/点击目标实测)的,文末给 Playwright 进阶版。

#!/usr/bin/env python3# mobile_seo_checker.py# 批量检测全站移动端适配问题(静态启发式版)importcsvimportsysimportrequestsfrombs4importBeautifulSoupfromurllib.parseimporturljoin,urlparse MOBILE_UA=("Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 ""(KHTML, like Gecko) Chrome/120.0 Mobile Safari/537.36")# 移动端 UA 头,模拟手机抓取HEADERS={"User-Agent":MOBILE_UA}classMobileSEOChecker:def__init__(self,start_url,max_pages=50):self.start=start_url self.domain=urlparse(start_url).netloc self.max_pages=max_pages self.visited=set()self.results=[]# 每条: (url, [issues])def_is_internal(self,url):returnurlparse(url).netloc==self.domaindef_fetch(self,url):try:r=requests.get(url,headers=HEADERS,timeout=10)ifr.status_code==200and"text/html"inr.headers.get("Content-Type",""):returnr.textexceptExceptionase:returnNonereturnNonedef_check_html(self,url,html):soup=BeautifulSoup(html,"html.parser")issues=[]# 1. viewport 配置vp=soup.find("meta",attrs={"name":"viewport"})ifnotvpor"width=device-width"notin(vp.get("content")or"").lower():issues.append("缺少/错误 viewport(应含 width=device-width)")# 2. 插件依赖(Flash/旧 object/embed)ifsoup.find("embed")orsoup.find("object")orsoup.find("param"):issues.append("检测到 embed/object(可能为插件依赖,移动端慎兼容)")# 3. 错误移动跳转:rel=alternate media=only screen 但指向不同页forlinkinsoup.find_all("link",rel="alternate"):media=(link.get("media")or"").lower()if"only screen"inmediaand"max-width"inmedia:issues.append("存在 rel=alternate media 移动跳转,需确认目标正确")# 4. 内联样式里的小字号(启发式)small_font_hits=0fortaginsoup.find_all(style=True):style=tag.get("style","").lower()fortokeninstyle.split(";"):token=token.strip()iftoken.startswith("font-size"):num="".join(chforchintokenifch.isdigit())ifnumandint(num)<12and"px"intoken:small_font_hits+=1ifsmall_font_hits:issues.append(f"发现{small_font_hits}处内联字号 <12px(可读性风险)")# 5. 图片缺尺寸(CLS 风险)imgs=soup.find_all("img")no_size=0forimginimgs:ifnotimg.get("width")andnotimg.get("height")andnotimg.get("srcset"):no_size+=1ifno_size:issues.append(f"{no_size}/{len(imgs)}张图片缺 width/height/srcset(布局抖动风险)")# 6. 横向溢出无法静态判定真实宽度,提示用真实浏览器复核returnissuesdefcrawl(self):queue=[self.start]whilequeueandlen(self.visited)<self.max_pages:url=queue.pop(0)ifurlinself.visited:continueself.visited.add(url)html=self._fetch(url)ifnothtml:continueissues=self._check_html(url,html)self.results.append((url,issues))# 收集内链继续爬soup=BeautifulSoup(html,"html.parser")forainsoup.find_all("a",href=True):next_url=urljoin(url,a["href"])ifself._is_internal(next_url)andnext_urlnotinself.visited:queue.append(next_url)defexport(self,path="mobile_seo_issues.csv"):withopen(path,"w",newline="",encoding="utf-8-sig")asf:w=csv.writer(f)w.writerow(["URL","问题数","问题明细"])forurl,issuesinself.results:w.writerow([url,len(issues)," | ".join(issues)ifissueselse"OK"])print(f"已导出{path},共检测{len(self.results)}个页面")if__name__=="__main__":target=sys.argv[1]iflen(sys.argv)>1else"https://example.com"checker=MobileSEOChecker(target,max_pages=50)checker.crawl()checker.export()# 打印有问题的页面bad=[(u,i)foru,iinchecker.resultsifi]print(f"\n发现{len(bad)}个页面存在移动端适配问题:")foru,iinbad:print(f"{u}\n - "+"\n - ".join(i))

运行示例

python mobile_seo_checker.py https://你的独立站.com

输出(示意):

发现 7 个页面存在移动端适配问题: https://site.com/product/a - 缺少/错误 viewport(应含 width=device-width) - 12/15 张图片缺 width/height/srcset(布局抖动风险) https://site.com/blog/old-post - 发现 3 处内联字号 <12px(可读性风险)

导出的mobile_seo_issues.csv

可直接交给开发排期修复。


四、静态检测不够?上真实浏览器(Playwright 进阶版)

字号大小、点击目标间距、横向溢出,必须真实渲染才能测准

。下面用 Playwright 量真实布局:

# mobile_seo_real.py(需 pip install playwright && playwright install chromium)fromplaywright.sync_apiimportsync_playwright MOBILE={"viewport":{"width":390,"height":844},# iPhone 12 逻辑分辨率"is_mobile":True,"has_touch":True,"user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15"}defaudit(url):withsync_playwright()asp:b=p.chromium.launch()pg=b.new_page(**MOBILE)pg.goto(url,wait_until="networkidle")# 横向溢出:文档宽 > 视口宽overflow=pg.evaluate("document.documentElement.scrollWidth > window.innerWidth")# 点击目标:找过小的可点元素small_targets=pg.evaluate("""() => { const els = [...document.querySelectorAll('a,button')]; return els.filter(e => { const r = e.getBoundingClientRect(); return (r.width>0 && r.height>0) && (r.width<48 || r.height<48); }).length; }""")print(f"{url}: 横向溢出={overflow}, 过小点击目标={small_targets}个")b.close()audit("https://你的站.com/product/a")

把它套进上面的MobileSEOChecker

,就能做"全站真实渲染体检"。


五、修复动作表(交给开发直接抄)

问题修复
缺 viewport
字号小正文 ≥ 16px,最小可点文字 ≥ 12px
点击目标小按钮/链接 ≥ 48×48 CSS px,间距 ≥ 8px
横向溢出用响应式布局,图片max-width:100%
图片缺尺寸加width/height属性或用aspect-ratio占位
插件依赖用 HTML5/CSS 替代 Flash

六、权威参考(自查与提交)

  • Google:移动优先索引
  • Google Search Central:移动易用性问题
  • web.dev:响应式设计基础
  • web.dev:点击目标尺寸
  • MDN:viewport meta 标签
  • PageSpeed Insights(测移动端 CWV)

七、总结

移动端适配不是"锦上添花",是 2026 年谷歌排名的入场券

。后台测试工具下线后,批量自测成了刚需——上面这套脚本,静态层免费扫全站,Playwright 层量真实体验,足够你每月做一次移动端体检。


本文工具来自公众号「全域SEO增长」,更多 SEO/GEO 实战脚本持续更新;想交流具体站点问题,欢迎在 CSDN 评论区或私信找我。 更多实战工具合集请看我的 CSDN 专栏。