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…

5、jeecg 笔记之 minidao 条件判断

1、前言 我们知道 mybatis 中的动态sql语句是基于 OGNL 表达式的。额外补充一点&#xff1a;mybatis 中的 #{} 和 ${} &#xff0c;可直接跳过。#{}表示一个占位符号&#xff0c;#{}接收输入参数&#xff0c;类型可以是简单类型&#xff0c;pojo、hashmap。 如果接收简单类型&a…

python函数-装饰器

python函数-装饰器 1.装饰器的原则--开放封闭原则 开放&#xff1a;对于添加新功能是开放的 封闭&#xff1a;对于修改原功能是封闭的 2.装饰器的作用 在不更改原函数调用方式的前提下对原函数添加新功能 3.装饰器的本质--闭包 4.装饰器 &#xff08;1&#xff09;简单的装饰器…

Math常用方法,String转float并且保留两位小数,除法

除法 public static double div(double v1, double v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 new BigDecimal(Double.toString(v1));BigDecimal b2 new BigDecim…

博弈总结

SG函数部分内容大多借(chao)鉴(xi)自zyf学长 也有一些自己独到的理解 Hackenbush和纳什均衡直接弃掉了 不平等博弈有空再看 题目还有很多没切完 不过确实是没时间了&#xff0c;毕竟博弈只是一小块内容。 经典博弈 博弈论入门之巴什博奕 博弈论入门之nim游戏 博弈论入门之威佐夫…

Android 设置手机屏幕亮度

1、工具类 /*** 作者&#xff1a;created by meixi* 邮箱&#xff1a;15913707499163.com* 日期&#xff1a;2019/3/20 10*/public class BrightnessTools {/*** 判断是否开启了自动亮度调节*/public static boolean isAutoBrightness(ContentResolver aContentResolver) {boo…

bzoj 4300

这题让我很容易想起了求最长上升子序列&#xff0c;但是直接朴素算法 O( n ^ 2 ) 会超时。 考虑数在 int 范围内&#xff0c;那只需要保存二进制下某位为 1 的数为结尾的最大长度即可。 #include"cstdio" #include"cctype" #include"algorithm" …

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(&…

代码中特殊的注释技术——TODO、FIXME和XXX的用处(转)

1、声明 本篇转自博客&#xff1a;http://blog.csdn.net/reille/ 2、转载内容 2.1、前言 今天在阅读 Qt Creator 的源代码时&#xff0c;发现一些注释中有 FIXME 英文单词&#xff0c;用英文词典居然查不到其意义&#xff01;实际上&#xff0c;在阅读一些开源代码时&#xff0…

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 ~/.…

@ConfigurationProperties + @EnableConfigurationProperties

1、ConfigurationProperties 在类上通过ConfigurationProperties注解声明当前类为属性读取类。 举例&#xff1a; ConfigurationProperties(prefix "jdbc") prefix"jdbc" 读取属性文件中&#xff0c;前缀为jdbc的值。 在类上定义各个属性&#xff0c;名称…

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

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