博客上线已有数月,但是由于是前后端分离开发,因此SEO优化做的并不好。经过不断地探索实践,终于让搜索引擎成功收录了网站的页面数据。如果你也正在开发前后端分离项目,正在为如何进行SEO优化而发愁,那么这篇文章将会帮助你提高搜索引擎收录。
前言
什么是SEO
我们每天都在使用搜索引擎查找各种各样的问题,只需要打开搜索引擎,输入几个简单的字,按一下回车,就能看到我们想要的内容了。但是每个搜索关键字都可以查询到成千上万的结果,对于搜索结果的排序,每个搜索引擎都有自己的算法,它会通过你所输入的搜索词语,运用自己的算法,把结果呈现给你。
因此,作为一个网站拥有者,你肯定希望可以把自己的网站信息放在靠前的地方,这就是体现SEO的价值的时候了。
首先我们先了解一下什么是SEO?
SEO: Search Engine Optimization,搜索引擎优化。利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。SEO是提高你网站排名的一个很有效的方法,这个完善和优化你网站的排名因素的方法就是能影响搜索引擎的排名的算法。 因此,SEO是网络营销策略 (online marketing Digital strategy)和数字营销策略 (Digital Marketing strategy)中很重要的一个环节。SEO可以提高你在搜索引擎的排名,进而使你的网站获取得更多的流量。
什么是SPA
SPA:Single Page Application ,单页面应用。这类应用的特点是网站的效果都是显示在一个静态页面中的,当用户进行页面切换时,其实并没有从一个页面中跳转到另一个页面中,只是通过 js 动态的将内容进行了修改。
spa页面的优点是用户更体验好,切换数据加载更快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染。而且渲染工作有客户端完成,大大减轻了服务器的请求处理压力。并且前后端分离开发,前端进行交互逻辑,后端负责数据处理,各司其职,分工更加明确。
但是它的缺点也是非常明显的,初次加载时要将基础的JavaScript、CSS 统一加载,部分页面按需加载。由于所有的内容都在一个页面中动态替换显示,但是爬虫蜘蛛在执行爬取的过程中, 不会去执行网页中的 JS 逻辑, 所以隐藏在 JS 中的跳转逻辑也不会被执行。所以在 SEO 上其有着天然的弱势,搜索引擎蜘蛛爬取不到页面的数据内容。
为什么做SEO优化
如果不对SPA应用做SEO优化的话,搜索引擎抓取到的网站标题与内容完全与实际效果不符,网站的关键信息无法被搜索引擎收录,那就更不用说用用户访问网站了。下图的情况,这这就是SPA应用未做SEO优化的效果,那么我们该如何解决这个问题呢?
优化方案选型
既然爬虫蜘蛛们如此的“不思进取”,没能力看到网页完全渲染后的html代码,那就只能从服务端出发,给搜索引擎返回符合它“胃口”的渲染后的完整页面,让搜索引擎直接收录网站。目前常用的思路有如下几种:
方案一:使用SSR
SSR是目前前端项目最常用的优化思路,页面上的内容是通过服务端渲染生成的,浏览器直接显示服务端返回的html就可以。虽然大大提高了首屏加载速度,拥有了更好的SEO效果。但同时存在项目改造成本大,学习成本相对较高,服务端压力较大的缺点。感兴趣的小伙伴可查阅官方文档改造项目
https://cn.vuejs.org/guide/scaling-up/ssr.html
方案二:使用代理爬虫渲染
除了在前端项目做文章外,也可以从后端出发,当监听到有网络爬虫请求时,将请求转发到后端的爬虫程序处理。爬虫程序获取到渲染后的网页代码,直接返回给爬虫蜘蛛。
但这样做也存在一个问题,爬虫处理需要等待页面全部加载完成后才能获取html代码,会导致请求时间过长,让爬虫蜘蛛误以为页面错误,请求超时的情况。且返回的html代码包含大量的css js等无关内容,爬虫蜘蛛并不能准确获取到关键的页面数据信息。
目前爬虫工具使用较多的有selenium、splash、playwright等,但是这类爬虫框架存在服务端部署麻烦的问题。建议使用docker部署爬虫服务,然后使用程序调用。
selenium部署使用参考:
https://github.com/SeleniumHQ/docker-selenium#quick-start
splash部署使用参考:
https://splash.readthedocs.io/en/stable/install.html#linux-docker
方案三:后端返回SEO专页
那么有没有一种方案,既可以避免SSR那样对前端项目大改,又可以避免爬虫代理的龟速渲染,还能直接返回最符合爬虫蜘蛛胃口的html页面呢?答案是有的,那就使用Django开发一个专门的SEO请求路由,前面使用nginx代理,当UA为爬虫请求时,直接反向代理到Django的SEO路由,返回一个纯净的,专门让爬虫蜘蛛查看的页面。
让搜索引擎知道你
提交网站
首先要做的是把你的网站信息告诉搜索引擎,让搜索引擎知道你的网站已经上线了,让搜索引擎知道你的存在。
谷歌:
https://search.google.com/search-console/index
百度:https://ziyuan.baidu.com/
必应:
https://www.bing.com/webmasters/home
头条:
https://zhanzhang.toutiao.com/
360:https://zhanzhang.so.com/
搜狗:
https://zhanzhang.sogou.com/
各家的提交流程都大致相同。先是注册账号,国内的话进行实名认证,然后提交网站地址域名信息,最后使用htlm或者cname等方式通过验证即可。
前端vue配置
提交完网站后,大概3-5天,就可以在各个搜索引擎通过site:你的域名搜索到网站的信息了。但此时显示的网站title和describe以及keyword都是错误的,以vite项目为例,此时就需要在vue页面的index.html文件head中添加title、keywords、description信息。参考文档:
https://www.vitejs.net/guide/#
index-html-and-project-root
崔亮的博客-专注devops自动化运维,传播优秀it运维技术文章
开启sitemap
现在搜索引擎已经知道了你的网站,并且可以正确的显示你的网站title和description信息。但是他抓取的信息是非常有限的,大部分的内容页面依然没有被正确的收录到搜索引擎中。此时你可以通过以下两种方式解决这个问题:
一是使用API接口提交,虽然API的及时性好,但是各个搜索引擎的API地址和参数都不一致,需要适配各个搜索引擎的API提交接口,工作量较大。
二是使用sitemap提交,Sitemap(站点地图)是一种文件的统称,通常Sitemap可以是txt或者XML格式。通过Sitemap你可以告诉搜索引擎关于你的站点中的网页、视频或者其他文件的相关信息,帮助搜索引擎更好的认识和理解你的站点。格式正确的Sitemap(站点地图)文件会帮助搜索引擎更高效地抓取你的网站。
在此推荐大家使用sitemap提交网站,不管有多少搜索引擎,只需要将sitemap地址告诉搜索引擎即可,sitemap是一个统一的标准,无需为各个搜索引擎做单独适配。
Django作为一个成熟的web框架,同样提供了完整的sitemap支持,我们只需要几行代码,就可以开启sitemap功能。参考文档
https://docs.djangoproject.com/en/3.2/ref/contrib/sitemaps/
安装应用(settings.py)
INSTALLED_APPS = [
'django.contrib.sites', # 站点框架
'django.contrib.sitemaps', # 网站地图
]
# 站点框架配置
SITE_ID = 1
接下来执行python manage.py migrate,创建相关数据库表结构,然后访问admin页面,修改站点信息。我的VUE前端域名为www.cuiliangblog.cn,Django后端域名为api.cuiliangblog.cn。将来生成的sitemap地址为www.cuiliangblog.cn/XXX。因此填写domain值为www.cuiliangblog.cn name值为崔亮的博客
添加根路由配置(urls.py)
由于我的博客网站分为文章和笔记两大模块,使用两个不同的模型存储,他们对应的处理逻辑不同,但是都需要搜索引擎收录。因此建立了一个sitemaps字典,包含ArticleSitemap和SectionSitemap两个视图,然后指向路由规则。
from django.urls import path, re_path, include
from django.contrib.sitemaps.views import sitemap
from public.sitemaps import ArticleSitemap, SectionSitemap
sitemaps = {
'blog': ArticleSitemap,
'section': SectionSitemap
}
urlpatterns = [
path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
# 网站地图
]
添加地图类处理逻辑(sitemaps.py)
当有
api.cuiliangblog.cn/sitemap.xml请求时,会交由ArticleSitemap与SectionSitemap类处理。由于我的博客网站文章地址为
https://www.cuiliangblog.cn/detail/article/XXX。笔记地址为
https://www.cuiliangblog.cn/detail/section/XXX。因此需要修改location配置,添加URL前缀/detail/article/
from django.contrib.sitemaps import Sitemap
from blog.models import Article, Section
class ArticleSitemap(Sitemap):
changefreq = "never" # 可选,指定每个对象的更新频率
priority = 1.0 # 可选,指定每个对象的优先级,默认0.5
def items(self): # 返回对象的列表.这些对象将被其他方法或属性调用
return Article.objects.all()
def lastmod(self, obj): # 可选,该方法返回一个datetime,表示每个对象的最后修改时间
return obj.modified_time
def location(self, obj): # 可选.返回每个对象的绝对路径.如果对象有get_absolute_url()方法,可以省略location
return "/detail/article/" + str(obj.id)
class SectionSitemap(Sitemap):
changefreq = "never" # 可选,指定每个对象的更新频率
priority = 0.5 # 可选,指定每个对象的优先级,默认0.5
def items(self): # 返回对象的列表.这些对象将被其他方法或属性调用
return Section.objects.all()
def lastmod(self, obj): # 可选,该方法返回一个datetime,表示每个对象的最后修改时间
return obj.modified_time
def location(self, obj): # 可选.返回每个对象的绝对路径.如果对象有get_absolute_url()方法,可以省略location
return "/detail/section/" + str(obj.id)
接下来访问
https://api.cuiliangblog.cn/sitemap.xml,就可以看到Django为我们生成的sitemap内容了。
修改nginx配置,添加反向代理规则
虽然已经生成了sitemap,但是访问的地址为
https://api.cuiliangblog.cn/sitemap.xml,当你提交到搜索引擎时,会要求你的sitemap地址必须与网站地址一致。也就是说,我们需要添加nginx反向代理设置,当我们访问
https://www.cuiliangblog.cn/sitemap.xml时,返回
https://api.cuiliangblog.cn/sitemap.xml的内容。
server {
listen 443 ssl http2;
server_name www.cuiliangblog.cn;
location /sitemap.xml {
proxy_pass http://127.0.0.1:8010; # 后端Django项目地址
}
location / {
root /opt/myblog_pc/dist; # VUE项目打包路径
index index.html index.htm;
try_files $uri $uri/ /index.html;
add_header Access-Control-Allow-Origin *;
}
}
接下来我们访问
https://www.cuiliangblog.cn/sitemap.xml,验证请求是否正常。
测试无误,接下来将sitemap地址提交到搜索引擎即可,以百度为例:
让搜索引擎看懂你
需求分析
提交完sitemap后,现在搜索引擎就可以正常的收录到所有在sitemap文件中的地址内容,接下来,我们需要做的就是为搜索引擎的蜘蛛单独开发一个用于SEO优化的html页面。当爬虫蜘蛛请求
https://www.cuiliangblog.cn/detail/article/46时,nginx根据请求UA判定是爬虫蜘蛛请求,反向代理到后端,URL请求路径更改为
https://api.cuiliangblog.cn/robots/article/46,响应的内容是经过处理后专门用于SEO爬取的页面。
后端开发SEO专页
添加根路由配置(urls.py)
添加一个路由规则,正则匹配内容的类型(文章还是笔记)以及内容的ID,传给views视图处理。
from django.urls import path, re_path, include
from public.views import RobotsAPIView
urlpatterns = [
path('robots//', RobotsAPIView.as_view(), name="robots"),
# 搜索引擎爬取内容接口
]
添加视图处理函数(views.py)
视图函数处理的逻辑是更具传入的内容类型,以及对应的ID,从数据库中取出相应的内容,返回给模板渲染即可。
import re
import markdown
from django.http import HttpResponse
from django.shortcuts import render
from rest_framework.views import APIView
from blog.models import Article, Section
from management.models import SiteConfig
from blog.models import Article, Section
class RobotsAPIView(APIView):
"""
搜索引擎爬取内容接口
"""
@staticmethod
def get(request, kind, content_id):
site = SiteConfig.objects.get(id=1)
if kind == 'article':
content = Article.objects.get(id=content_id)
# 提取keyword
keyword = content.category.name
for i in content.tags.all():
keyword = keyword + ',' + i.name
else:
content = Section.objects.get(id=content_id)
keyword = content.note.name
html_body = markdown.markdown(content.body) # 文章正文使用markdown存储
# 去除a标签
body_a = re.sub(r"""]+\bhref="([^"]*)"[^>]*>([\s\S]*?)""", " ", html_body)
# 去除img标签
body = re.sub(r"""""", " ", body_a)
return render(request, 'robots.html', locals())
模板页面(rebots.html)
模板页面就是接收view视图返回的数据,渲染出更符合爬虫蜘蛛喜欢格式的html内容即可。
{{content.title}}-{{site.name}}
{{content.title}}
{{body|safe}}
接下来访问测试,可以看到,已经是一个非常简单的符合爬虫蜘蛛胃口的html内容了。
nginx配置
接下来就更改nginx配置,根据UA判定,如果是爬虫蜘蛛请求,直接反向代理到后端Django服务处理即可。
server {
listen 443 ssl http2;
server_name www.cuiliangblog.cn;
location /sitemap.xml {
proxy_pass http://127.0.0.1:8010; # 后端Django项目地址
}
location ~* /detail\/(section|article)/(.*) {
set $kind $1;
set $content_id $2;
if ( $http_user_agent ~* "Baiduspider|Googlebot|360Spider|Bingbot|Sogou Spider|Yahoo! Slurp China|Yahoo! Slurp|twitterbot|facebookexternalhit|rogerbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator" ) {
proxy_pass http://127.0.0.1:8010/robots/$kind/$content_id; # 后端Django项目地址
}
proxy_pass http://127.0.0.1:8011; # VUE处理请求
}
location / {
proxy_pass http://127.0.0.1:8011; # VUE处理请求
}
}
访问验证
我们模拟普通浏览器用户访问
https://www.cuiliangblog.cn/detail/article/46,返回的是SPA应用源码,需要浏览器渲染才能加载数据。
接下来我们模拟爬虫蜘蛛访问,返回的是专门用于SEO抓取的页面数据。
等待几天后再次使用搜索引擎查看抓取结果,就发现已经正常显示网站页面的相关内容了。
让搜索引擎重视你
SEO优化排名靠前是一个非常专业的问题,一般公司都有专门的SEO岗位负责优化排名,通常需要花钱购买排名靠前的位置,在此我就不做过多描述,仅提供一个通用的优化思路。参考文章:
https://www.zhihu.com/question/19808905