AngularJs自学心得

1.angularjs的SEO问题解决方案

我的前端用到angularjs,服务器用到nginx。 

大体流程:

nginx服务器检测到爬虫访问,跳转到专门的url,此url是angularjs已经渲染过后的页面。非常的简单。

  a).首先是angularjs的渲染问题

    angular添加一个模块‘seo’,引入文件 angular-seo.js文件(附件中有)。

     <script src="js/app/angular-seo.js"></script>

     angular.module('app', ['ng', 'seo']);

     然后你可以在每个controller中,觉得页面差不多已经创建好之后调用 $scope.htmlReady()(就是数据请求完成之后,随便你放哪里)。

     然后用phantomjs进行页面的渲染,安装完成之后(自己百度怎么安装,很简单),用下面代码进行调用。

     phantomjs --disk-cache=no /path/xxxxxx...../angular-seo-server.js 9001 http://localhost:8080

     这个就是开启9001端口,调用angular-seo-server.js文件(附件中有)获得8080端口渲染的页面,渲染完成标志就是上面的$scope.htmlReady()。 

     localhost:9001这个url地址就是爬虫应该访问的地址。

   b).让nginx知道爬虫进行访问

     在实际页面head中加入下面代码

     <meta name="fragment" content="!" >

    爬虫看到这段代码之后,它会知道这个页面有动态的javascript需要爬取。它会在你的url中添加?_escaped_fragment_=/,这个标志就是让nginx知道是爬虫进行访问了 

     nginx中进行下面配置

     if ($args ~ _escaped_fragment_) { #这里面写你们的处理代码 rewrite ^ /bot/ ; }

     还有angularjs的路径时 xxx/#/xxxx这种形式,爬虫是没办法识别 /#/之后的内容的,所以我们需要改成 xxxxx/!#/xxxxxx这种形式,很简答,添加下面代码即可

     angular.config(['$routeProvider','$locationProvider', function ($routeProvider, $locationProvider,$httpProvider) { $routeProvider.when('/index', { templateUrl: '', controller: '' }); $locationProvider.hashPrefix('!'); }]);

   c).跳转url,地址我们已经有了,即为localhost:9001,nginx配置如下(与前面的if语句代码呼应) 

     location /bot/ { proxy_pass http://localhost:9001/; proxy_http_version 1.1; proxy_set_header Host $host:80; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forworded-For          $proxy_add_x_forwarded_for; proxy_set_header Via "nginx"; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";

     注意:proxy_pass中的url地址一定要以“/"结尾,就是这个东西,我调试了大半天才搞出来,因为没有“\”则方位地址会变成 xxxx/bot/?_escaped_fragment_=/xxxxx,这样是不对的,应该是xxxx/?_escaped_fragment_=/xxxxx。

   这样就大功告成了。以后只要在适当的地方添加$scope.htmlReady()即可。ps:经过测试貌似不需要$scope.htmlReady()

   d).测试可以使用curl

     例如本地测试 curl localhost:9001,最终测试 curl host/?_escaped_fragment_=/ ,这会返回页面内容,查看一下是否渲染完成即可。

   测试:监听时,url没带上相对路径(https://www.hansap.com/XXX)

  解决办法:

       通过github查到phantomJs官网,查看API,request包含的信息。

    

 

     可以在angular-seo-server.js内把头部信息打印出来。既然如此,如果想对路径(/protal/product/1000)没带过来,那就可以在nginx端做处理。把爬虫的请求路劲塞到头部信息内(real_url $request_uri),然后在phontomJs端用request取到。

     

 

      nginx配置: 

      server{

          ......

          if ( $http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot|HaosouSpider|360Spider|Bingbot" ) {

                rewrite ^ /bot/ ;

         }

        location /bot/ {

                proxy_pass http://192.168.11.179:9001/;

                proxy_http_version 1.1;

                proxy_set_header real_url $request_uri;    //请求想对路劲

                proxy_set_header Host $host:80;

                proxy_set_header X-Real-IP $remote_addr;

                proxy_set_header X-Forworded-For $proxy_add_x_forwarded_for;

                proxy_set_header Via "nginx";

                proxy_set_header Upgrade $http_upgrade;

                proxy_set_header Connection "upgrade";

        }

    }

 解决思路:

    a).定位问题

        a.在angular-seo-server.js端打印出request.url每次都为'/'

        问题为nginx重定向时,URL地址的想对路劲没带过来

    b).解决问题

        a.在phantomJsAPI中查出request的信息,可以查到头部相关信息,这就简单了,只需要在nginx重定向时,把想对路径加到头部信息即可

        b.nginx中配置 proxy_set_header real_url $request_uri;

            real_url(自定义名称) $request_uri(nginx全局变量:想对路径);

        c.phantomJs端取到想对路径即可

 

2.优化AngularJs的URL # 号问题

  a).在index.html页面添加<base href="/">

  b).在路由js内添加

      .config(

            ['$stateProvider', '$urlRouterProvider','$locationProvider',

              function($stateProvider, $urlRouterProvider,$locationProvider) {

                ......

                $locationProvider.html5Mode(true);

                /*var mode = {enabled:true,requireBase:false,rewriteLinks:true};

                $locationProvider.html5Mode(mode);

                $locationProvider.html5Mode(true).hashPrefix('!');*/

              }

           ]

      );

  c).定义前台过滤器(Filter)

    <filter>

        <filter-name>pageFilter</filter-name>

        <filter-class>com.whicloud.filter.PageFilter</filter-class>

        <init-param>

            <param-name>prefix</param-name>

            <param-value>/ajax;/buildrequest;/download;/upload</param-value>

        </init-param>

        <init-param>

            <param-name>suffix</param-name>

            <param-value>.do;.action</param-value>

        </init-param>

        <init-param>

            <param-name>include</param-name>

            <param-value>.</param-value>

        </init-param>

    </filter>

 

    <filter-mapping>

        <filter-name>pageFilter</filter-name>

        <url-pattern>*</url-pattern>

    </filter-mapping>

 

    public class PageFilter implements Filter {

   private final static Logger log = LoggerFactory.getLogger(PageFilter.class);

 

    private final static List<String> PREFIX_MATCH = new ArrayList<>();

    private final static List<String> SUFFIX_MATCH = new ArrayList<>();

    private final static List<String> INCLUDE_MATCH = new ArrayList<>();

 

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

        log.info("初始化page filter");

 

        //前缀

        String prefix = filterConfig.getInitParameter("prefix");

        if (!StringUtils.isEmpty(prefix)) {

            String[] prefixs = prefix.split(";");

            PREFIX_MATCH.addAll(Arrays.asList(prefixs));

        }

 

        //后缀

        String suffix = filterConfig.getInitParameter("suffix");

        if (!StringUtils.isEmpty(suffix)) {

            String[] suffixs = suffix.split(";");

            SUFFIX_MATCH.addAll(Arrays.asList(suffixs));

        }

 

        //包含

        String include = filterConfig.getInitParameter("include");

        if (!StringUtils.isEmpty(include)) {

            String[] includes = include.split(";");

            INCLUDE_MATCH.addAll(Arrays.asList(includes));

        }

 

        log.info("初始化page filter完成");

    }

 

    private boolean isMatch(String uri) {

        for (String prefix : PREFIX_MATCH) {

            if (uri.startsWith(prefix))

                return true;

        }

 

        for (String suffix : SUFFIX_MATCH) {

            if (uri.endsWith(suffix))

                return true;

        }

 

        for (String include : INCLUDE_MATCH) {

            if (uri.indexOf(include) >= 0)

                return true;

        }

        return false;

    }

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;

        String root = req.getContextPath();

        String uri = req.getRequestURI();

        uri = uri.substring(root.length());

 

        if (isMatch(uri)) {

            chain.doFilter(request, response);

        } else {

            req.setAttribute("root", root);

            req.getRequestDispatcher("/index.html").forward(request, response);        //服务器端重定向到首页,前台angularJs会自动吧路由状态带上,并解析

        }

    }

    @Override

    public void destroy() {

    }

    }

 

转载于:https://www.cnblogs.com/yield/p/8465950.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/414671.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 人脸识别进行实名验证demo

实名验证简介&#xff1a;http://ai.baidu.com/docs#/Face-PersonVerify-V3/top 1、首先到百度云平台——人脸识别项创建应用 https://console.bce.baidu.com/?fromai1#/aip/overview 2、创建应用之后、下载SDK SDK链接&#xff1a;https://download.csdn.net/download/meix…

Hibernate 补充 ManyToOne、OneToMany、OneToOne的使用例

1、前言 Hibernate 为程序员提供一种级联操作&#xff0c;在编写程序时&#xff0c;通过 Hibernate 的级联功能可以很方便的操作数据库的主从表的数据&#xff0c;我们最常用的级联是级联保存和级联删除。2、ManyToOne | OneToMany 单词误导 当我们去试用的时候&#xff0c;首先…

移动端使用页尾文字使用绝对定位遇到input框会飘起来的处理方案

如下版权信息的样式在遇到input框的时候会跟随输入框其后 优雅的解决方式&#xff1a;&#xff08;定位遇上键盘飘窗解决&#xff09; mounted里面写上&#xff1a;var originalHeightdocument.documentElement.clientHeight || document.body.clientHeight; //console.info(&…

Android 解决导入多个module时jar包冲突

1、在后导入的module中编译先前导入的module compile project(path: :faceplatform) 2、删除后导入的module里面的和先前导入的module的重复jar包&#xff0c; 同理jniLibs里面重复的so文件也需要删除 在线回复bug:qq1085220040

linux 添加环境变量(php为例)

find / -name php vim /etc/profile 文件最后添加 export PATH$PATH:/usr/local/php/bin source /etc/profile php -v 这时只实现了当前ssh 登录时可以PHP&#xff0c;如果退出重新登录就不能使用PHP了 解决&#xff1a; vim ~/.bashrc 添加 source /etc/profile source ~/.…

Android 活体人脸实时采集,百度、虹软

百度现在功能较少——使用虹软&#xff0c;方便 虹软官网&#xff1a;https://ai.arcsoft.com.cn/ucenter/resource/build/index.html 申请应用&#xff0c;下载SDK即可 虹软已修改好的&#xff0c;可注册人脸&#xff0c;人脸验证成功——登陆的demo&#xff1a;https://down…

Android 最新左右可见上下页的banner实现demo

运行效果&#xff0c;可见上下页样式 demo链接&#xff1a;https://download.csdn.net/download/meixi_android/11045703 实现方法 首先添加必要依赖 implementation (com.android.support:recyclerview-v7:27.0.2){force true } implementation (com.android.support:cardv…

WIN10下微信崩溃(已经是最新版)的解决方法

问题症状&#xff1a;WIN10下运行最新版微信&#xff08;CrashVersion1644560715&#xff09; ---------------------------微信运行错误---------------------------你的微信崩溃次数较多&#xff0c;建议使用最新版本&#xff0c;点击"确定"到官网(http://pc.weixi…

o.s.b.d.LoggingFailureAnalysisReporter

1、错误信息 *************************** APPLICATION FAILED TO START ***************************Description:Field userMapper in club.sscai.userservice.user.service.UserService required a bean of type club.sscai.userservice.user.mapper.UserMapper that could …

前端学习(2733):重读vue电商网站43之使用 lodash 中 cloneDeep(obj) 来实现深拷贝

lodash 官方文档传送门 Using npm Js $ npm i -g npm $ npm i --save lodash_.cloneDeep(value) 使用 项目中使用 cloneDeep 需求&#xff1a;由于 addForm 中商品所属的分类数组 goods_cat在商品分类模块需要使用 v-model 进行双向绑定数组形式&#xff0c;而我们调用添加商品…

Spring Data JPA框架

1、前言 扔一个 spring data jpa 的代码&#xff0c;可运行&#xff0c;后续补充博客内容。 环境&#xff1a;eclipse tomcat8 2、部分截图 3、源码 https://gitee.com/niceyoo/jpa-demo 4、sql 既然都是 spring data jpa &#xff0c;还要啥数据库呀&#xff0c;自己创建一个…

jdk1.7 String switch的实现

对于int的switch&#xff0c;jvm是用tableswitch和lookupswitch来实现的&#xff0c;jdk1.7 switch增加了对string的支持&#xff0c;那么底层是如何实现的呢&#xff1f;是否增加了新的指令或是否给某些指令增加了新的含义&#xff1f; 看这样一个程序&#xff1a; Java代码 …