Vue2前后端分离项目SSR优化SEO(基于Python)

Vue2前后端分离项目SSR优化SEO(基于Python)
#### 搜索引擎爬取机制 类似普通爬虫,不会加载js文件,如果内容是动态加载则无法获取真实内容 #### 解决方案 1、SSG静态站点(不适用,pass) 2、SSR服务端渲染 #### 实现SSR的方式 传统可以自己在前端项目中建一个服务器,或者使用框架(Nuxt.js)。这种会有一个问题,那就是特定于客户端的功能无法使用,但是我的项目又有许多这种东西,且使用Nuxt.js需要重构整个项目,实在不现实。 #### 替代方案 我们基于自建服务器的思想,可以自建一个服务器来专门针对搜索引擎来反馈真实数据,同时对于客户端的请求则不通过这个服务器,这样也可以大大减轻服务器压力。 这个时候我们会想到通过服务器将url真实的数据请求得到后返回给搜索引擎,同时在服务器上做好流量转发。这时服务器语言我们选择Python,因为方便。 #### 流量转发 我们可以通过修改nignx配置来实现 ```shell # 定义非客户端请求的特征(包括搜索引擎、爬虫、API请求工具等) set $is_non_client false; # 匹配常见的爬虫、bot和工具的User-Agent if ($http_user_agent ~* "Googlebot|Bingbot|BaiduSpider|Spider|Crawler|bot|Slurp|Mediapartners|AdsBot|bingbot|google-PageRenderer|googleweblightcrawler|googlebot-mobile|googlebot-image|Googlebot-Image|Googlebot-Video|Googlebot-Mobile|Google Web Preview|googleweblight|Googlebot|Google-PageRenderer|Googlebot/2.1|Google-PageRenderer/1.0|Googlebot/1.0|Googlebot-Mobile/1.0|curl|Postman|HTTPie|Unirest|python-requests|Java|okhttp|Apache-HttpClient|libcurl|libcurl|libcurl/|libcurl/|curl/|curl/|wget|HTTPClient|HTTP/1.1|HTTP/1.0|HTTP/2.0|HTTP/1.1|HTTP/1.1|PostmanRuntime-ApipostRuntime/1.1.0") { set $is_non_client true; } location /article { # 如果是非客户端请求,转发到另一个URL if ($is_non_client = true) { #return 200 "$request_uri"; proxy_pass https://exmaple.com$request_uri; } # 处理正常请求的静态文件 try_files $uri $uri/ /index.html; } location / { # 处理正常请求的静态文件 try_files $uri $uri/ /index.html; } ``` 这样我们可以将搜索引擎的流量转发到https://exmaple.com$request_uri中,再使其返回真实数据就可以了。 #### 服务端 我们可以使用**selenium**来模拟浏览器从而获取真实数据 ```python import time from flask import Flask from selenium import webdriver from selenium.webdriver.firefox.options import Options from selenium.webdriver.firefox.service import Service from bs4 import BeautifulSoup app = Flask(__name__) driver_path = "/usr/local/bin/geckodriver" # 配置无头模式 options = Options() options.add_argument('--headless') # 无头模式 options.add_argument('--no-sandbox') # 禁用沙盒模式(Linux上必需) options.add_argument('--disable-gpu') # 禁用GPU加速 options.add_argument('--disable-dev-shm-usage') # 禁用共享内存 options.binary_location = "/usr/bin/firefox" driver_path = Service(executable_path=driver_path) # 初始化WebDriver driver = webdriver.Firefox(service=driver_path, options=options) @app.route("/article/<id>", methods=["GET"]) def tvm(id): try: url = 'https://exmaple.com/' + id #替换为自己前端真实地址 driver.get(url) # 等待JavaScript执行完成(根据实际情况调整等待时间) time.sleep(5) # 获取页面源码 html = driver.page_source # 解析HTML内容 soup = BeautifulSoup(html, 'html.parser') return str(soup) except Exception as e: print(f"发生错误:{e}") if __name__ == '__main__': app.run(host='0.0.0.0', port=3000, debug=True) ``` 这样可以获取到真是的内容,可是我们服务器资源有限,开启浏览器会消耗较多资源,且时间较久。这时候我们会想到我们只需要要返回真实数据就可以了,无需在意其他,那么我们可以直接去连接数据库,获取所需要的内容再按照html形式返回就可以了,当然也可以直接请求后端接口来获取数据,这里我为了减轻后端服务器压力就不采用。 #### 优化 ```python import mysql.connector from flask import Flask,render_template_string # 连接到数据库 conn = mysql.connector.connect( user='root', password='root', host='127.0.0.1', database='database' ) query = "SELECT article_title, article_content, view_count, update_by FROM article WHERE id = %s AND deleted = 0" cursor = conn.cursor() str = """ <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{keywords}}</title> <meta content="{{keywords}}" name="keywords"/> <meta content="文章浏览阅读{{count}}次。{{description}}" name="description"/> <meta content="{{author}}" name="author"/> <link href="https://api.timeplanet.cn/documents/article/{{id}}" rel="canonical"/> </head> <body> <h1 style="display: none;"> {{keywords}} </h1> <div class="article-title" data-v-54aad278=""> {{keywords}} </div> <div> {{body}} </div> </body> </html> """ app = Flask(__name__) @app.route("/article/<id>", methods=["GET"]) def tvm(id): cursor.execute(query, (id,)) rows = cursor.fetchall() data = { 'keywords': rows[0][0], 'description': rows[0][1], 'author': rows[0][3], 'body': rows[0][1], 'id': id, 'count': rows[0][2] } return render_template_string(str,**data) if __name__ == '__main__': app.run(host='0.0.0.0', port=3000, debug=True) ``` #### 完结撒花 到这里我们就完成了SSR的搭建了,对于那种项目不方便迁移的,客户端特定功能使用过多的项目是是十分的友好。