Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 427|回复: 0

AngularJS 解决 SEO 问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-11 17:41:10 | 显示全部楼层 |阅读模式

    由于 AngularJS 返回的是HTML模板,实际的内容需要执行JS以后才会填充进去,导致百度抓取蜘蛛抓不到,因此产生了 AngularJS 的 SEO 问题。经过几天的研究试验,我们的解决方案是这样的:在后台弄一个 PhantomJS 服务,判断是百度蜘蛛的请求后,就把请求转发给 PhantomJS,由它来解释执行JS,并返回输出给百度蜘蛛。
    下面详细说一下具体实现:
    后端的项目使用PHP的Zend1框架写的,只用于提供数据接口,前端使用AngularJS1。项目部署在Ubuntu上的Apache上面的。

    去掉URL中的“#”

    由于 AngularJS 的原因,生成的 URL 中带有“#”,AngularJS需要通过“#”后面的部分来进行页面路由,但百度蜘蛛看不到URL中#之后的部分,所以第一步便是去掉 URL中的 “#”。
    js/config/reoute.js 中注入 $locationProvider 对象,$locationProvider需要页面指定<base>路径,这样去掉了#之后能能正确加载js,css文件。

    .config(['$stateProvider', '$urlRouterProvider','$httpProvider','$locationProvider',
    	function($stateProvider,$urlRouterProvider,$httpProvider,$locationProvider){
            // ...
            $locationProvider.html5Mode(true);
    

    然后是index.html,这是主要的模板,js,css路径是相对于<base>的。

    <html>
    // ...
    <head>
        <script type="text/javascript" src="/dist/js/vendor.js"></script>
        <script type="text/javascript" src="/dist/js/app.js?v=1.0.3"></script>
        
        <base href="/">
    </head>
    <body>
    

    请求404的问题

    取消"#"之后,可以让百度蜘蛛直接访问我们的每个页面了,请求来了,判定为百度蜘蛛,则转发给 PhantomJS 来处理,但问题也出现了,用户正常的访问却变成了404!这是因为URL中“#”后面的部分是AngularJS设定的路由规则,跟我后端没有任何关系,所以会转到404,并返回了。
    解决办法就是重写.htaccess规则,让404指向index.html,这样就又走前端路由了。进入正常的前端路由,发送 ajax 请求后端数据再进行页面渲染。
    .htaccess文件如下,放/public/根目录下:

    RewriteEngine On
    
     RewriteCond %{REQUEST_FILENAME} -s [OR]
     RewriteCond %{REQUEST_FILENAME} -l [OR]
     RewriteCond %{REQUEST_FILENAME} -d
     RewriteRule ^.*$ - [NC,L]
    
    RewriteRule ^ /index.html
    

    要知道原php项目配置中是指向index.php的。改成这个重写规则,就产生一个新问题,php框架的入口文件index.php也在/public/目录下面,当前端发送ajax请求时,默认接收请求的是index.html,而不是index,php,这就导致ajax请求无法到达。
    在之前没有去掉“#”的时候,访问http://www.xxx.com/#/path/sss,请求只到达http://www.xxx.com,重定向到index.html,然后AngularJS读取history对象获得URL,进行路由控制,发出ajax请求(http://www.xxx.com/path/sss),进入index.php,返回相应数据。
    我们的解决办法就是把前端项目和后端项目分离出来,前端项目用原有的域名:http://www.xxx.com,而后端项目用:http://api.xxx.com,这样,后端php默认指向index.php,前端项目默认指向index.html。需要在apache中设置一下跨域可访问。为了方便部署,直接把前端项目命名为angular并放在public目录下面,实际上这是两个项目。
    前端项目

    <VirtualHost *:80>
    	ServerName www.xxx.com
    	DocumentRoot /path/xxx/public/angular
    	DirectoryIndex index.html
    	<Directory /path/xxx/public/angular>
    	AllowOverride all
    	require all granted
    	</Directory>
    </VirtualHost>
    

    后端项目

    <VirtualHost *:80>
    	ServerName api.xxx.com
    	DocumentRoot /path/xxx/public/
    	DirectoryIndex index.php
            Header set Access-Control-Allow-Origin "http://www.xxx.com"
            Header set Access-Control-Allow-Credentials true
    	<Directory /path/xxx/public/>
    	AllowOverride all
    	require all granted
    	</Directory>
    </VirtualHost>
    

    到目前为止,“#”去掉了,用户也能正常访问了,下面就是处理抓取了。

    搭建后端js环境

    首先,angular项目中.htaccess需要添加几行,变成这样:

    RewriteEngine On
    
     RewriteCond %{REQUEST_FILENAME} -s [OR]
     RewriteCond %{REQUEST_FILENAME} -l [OR]
     RewriteCond %{REQUEST_FILENAME} -d
     RewriteRule ^.*$ - [NC,L]
    
    RewriteCond %{HTTP_USER_AGENT} baiduspider|Googlebot|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator|Bingbot|360Spider|Yisouspider|Sogouspider [NC]
    RewriteRule (.*) http://seo.xxx.com/url/http://www.xxx.com/$1 [P,L]
    
    RewriteRule ^ /index.html
    

    表示如果请求来自搜索引擎蜘蛛,则重定向http://seo.xxx.com。我们在这个域名上部署了一个 PhantomJS 服务。

    先弄node环境:

    var express = require('express')
    var app = express()
    app.get('/url/http://*', function (req, res) {
        var content = '';
        var ourl = req.params[0];
        if(!(ourl.indexOf('.css')>-1 || ourl.indexOf('.js')>-1 ||ourl.indexOf('.png')>-1)){
            var url = "http://"+req.params[0].replace('_','#');
            var exec = require('child_process').exec, last = exec('casperjs casperjs_process.js '+url);
            last.stdout.on('data', function (data) {
                content += data;
            });
            last.on('exit', function (code) {
                res.send(content);
            });
        }
    })
    app.listen('3000','127.0.0.1');
    

    再弄 PhantomJS 服务

    var casper = require('casper').create(
        {
            pageSettings: {
                loadImages: false,
                loadPlugins: true,
                userAgent: 'Mozilla/5.0.8 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36 LBBROWSER'
            },
            logLevel: "debug",//日志等级
            verbose: false, // 记录日志到控制台
            waitTimeout:5000
        }
    );
    var url = casper.cli.get(0);
    casper.start(url, function() {});
    casper.waitForSelector('.ajax-end', function() {});
    casper.then(function(){
        this.echo(this.getPageContent());
    });
    casper.run();
    

    这个服务会解释执行所有JS然后返回带有内容HTML响应数据给百度蜘蛛。

    PS:个人博客链接:Blog:AngularJS 解决 SEO 问题

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-23 14:59 , Processed in 0.057039 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表