js提取指定网站内容

js提取指定网站内容

事实:自媒体运营需要转什么,所以我就把我这几天

网站优化优采云 发表了文章 • 0 个评论 • 88 次浏览 • 2022-09-21 11:07 • 来自相关话题

  事实:自媒体运营需要转什么,所以我就把我这几天
  js提取指定网站内容:这几天很多同学私信问我现在自媒体运营需要转什么,所以我就把我这几天关于这个问题的测试记录给大家分享一下:我自己测试,更新的时间就是2019.08.02号,文章数量是40篇,这种很像上班时间的分享又像某宝发货的提货提醒,反正你自己判断。在videotap看了一下全网的收益情况。同样一篇文章我在5年前看是每个月2000多,5年后转2018063100。
  
  同样的也是和今日头条一样三倍速度的翻阅。但是这样的效果依然很低,因为你得转100多篇才算完全转换,但是现在我们都很快地完成了一万篇,我同样也看了很多号做做点什么就10w+了。通过我个人观察和计算的情况,效果和收益差距很大很大很大。我刚看完可以推算出几个问题,这些问题都是转化的大小决定的。第一个问题:收益差距决定了你现在需要什么,如果你是要广告收益为主的话,你就需要多多的后期推广来获取收益,不能仅仅依靠前期积累的这些网站内容来提升收益。
  这个收益和自媒体运营又有很大的关系,要么是个人有大量的时间做内容,要么你有能力推广和投放广告,所以这个是有相互影响。第二个问题:你还要看转换率。就是你的收益和你的粉丝数量比值。当你的粉丝量积累达到了一定的量级,你的转换率达到了100%。当你的转换率在100%时候,你的收益就很恐怖。好多账号也是到这个程度,可能一篇文章也没有关注量。
  
  可能一篇文章也没有百度收录。那么这个就是你的转换率决定的。很多号是转化率需要一定的才可以触发收益,也就是说,你转换率达到100%以上才会有收益,如果达不到100%,你的收益就不多。第三个问题:你还要看粉丝数量、平台流量的占比。通过videotap我们看了下网站的阅读量,通过哪个点击量、哪个关键词,阅读量最高。
  这个就很好的决定了你转换率。可能今日头条就是因为一些其他原因转换率特别高。所以你有时间测试就可以通过上面的情况去判断平台的流量占比。因为现在很多网站已经能直接帮助你来测试你的文章是否有收益了。比如我同时测试了百家号和企鹅号。测试平台二者会按照你发布文章的先后来做阅读量的掉。先是百家号,掉的量比企鹅号更多。
  但是很有意思的一个情况,企鹅号掉的更快,而百家号呢,反而降低了。这是文章的转换率高低和网站的占比决定的。欢迎一起交流、沟通、思考。 查看全部

  事实:自媒体运营需要转什么,所以我就把我这几天
  js提取指定网站内容:这几天很多同学私信问我现在自媒体运营需要转什么,所以我就把我这几天关于这个问题的测试记录给大家分享一下:我自己测试,更新的时间就是2019.08.02号,文章数量是40篇,这种很像上班时间的分享又像某宝发货的提货提醒,反正你自己判断。在videotap看了一下全网的收益情况。同样一篇文章我在5年前看是每个月2000多,5年后转2018063100。
  
  同样的也是和今日头条一样三倍速度的翻阅。但是这样的效果依然很低,因为你得转100多篇才算完全转换,但是现在我们都很快地完成了一万篇,我同样也看了很多号做做点什么就10w+了。通过我个人观察和计算的情况,效果和收益差距很大很大很大。我刚看完可以推算出几个问题,这些问题都是转化的大小决定的。第一个问题:收益差距决定了你现在需要什么,如果你是要广告收益为主的话,你就需要多多的后期推广来获取收益,不能仅仅依靠前期积累的这些网站内容来提升收益。
  这个收益和自媒体运营又有很大的关系,要么是个人有大量的时间做内容,要么你有能力推广和投放广告,所以这个是有相互影响。第二个问题:你还要看转换率。就是你的收益和你的粉丝数量比值。当你的粉丝量积累达到了一定的量级,你的转换率达到了100%。当你的转换率在100%时候,你的收益就很恐怖。好多账号也是到这个程度,可能一篇文章也没有关注量。
  
  可能一篇文章也没有百度收录。那么这个就是你的转换率决定的。很多号是转化率需要一定的才可以触发收益,也就是说,你转换率达到100%以上才会有收益,如果达不到100%,你的收益就不多。第三个问题:你还要看粉丝数量、平台流量的占比。通过videotap我们看了下网站的阅读量,通过哪个点击量、哪个关键词,阅读量最高。
  这个就很好的决定了你转换率。可能今日头条就是因为一些其他原因转换率特别高。所以你有时间测试就可以通过上面的情况去判断平台的流量占比。因为现在很多网站已经能直接帮助你来测试你的文章是否有收益了。比如我同时测试了百家号和企鹅号。测试平台二者会按照你发布文章的先后来做阅读量的掉。先是百家号,掉的量比企鹅号更多。
  但是很有意思的一个情况,企鹅号掉的更快,而百家号呢,反而降低了。这是文章的转换率高低和网站的占比决定的。欢迎一起交流、沟通、思考。

js提取指定网站内容-苏州安嘉匹配率500%

网站优化优采云 发表了文章 • 0 个评论 • 88 次浏览 • 2022-09-08 19:16 • 来自相关话题

  js提取指定网站内容-苏州安嘉匹配率500%
  js提取指定网站内容
  一、前言提取是api调用的最基本的一步。在应用程序中,经常需要读取网页,或者更有可能的是对网页进行页面上的内容提取。采用调用javascript的方式进行提取,javascript是从网页中获取动态响应,从而能够从javascript请求网页中的更多数据,转而对网页进行静态化,呈现于页面之中。
  
  采用javascript进行这种提取一般需要以下几步:
  1、读取网页,并匹配重定向http头获取body流,获取响应page_url。在获取响应body流的page_url后,遍历整个网页,依次匹配相应的body流,并计算出提取结果。
  2、读取提取结果,将提取结果依次放置到对应的javascript中,并计算出提取值的base64编码。
  
  3、将提取值转换为base64编码的javascript文件。根据base64编码结果,可以计算出被提取的图片链接。
  二、提取规则总体思路:从0开始,给重定向http头匹配正则表达式,计算出匹配率,通过http头约束,根据不同的匹配率分配不同的抓取规则,将匹配链接中的内容提取。例如:匹配率低于70%时,则不进行抓取。只抓取匹配率达到70%以上的规则,将该规则提取出来。
  1、正则提取匹配率http头规则::正则表达式匹配上限:500^^$一次通用问题的目标链接:/input/a#innerhtml匹配率500%*imgfor://user-agent:''*imgfor://user-agent:''*server:''*input://source=''*offset://http/input*img://user-agent:''*input://user-agent:''*text://user-agent:''*input://user-agent:''*input://inputis://(site:''*)*regexp://*sites://***。 查看全部

  js提取指定网站内容-苏州安嘉匹配率500%
  js提取指定网站内容
  一、前言提取是api调用的最基本的一步。在应用程序中,经常需要读取网页,或者更有可能的是对网页进行页面上的内容提取。采用调用javascript的方式进行提取,javascript是从网页中获取动态响应,从而能够从javascript请求网页中的更多数据,转而对网页进行静态化,呈现于页面之中。
  
  采用javascript进行这种提取一般需要以下几步:
  1、读取网页,并匹配重定向http头获取body流,获取响应page_url。在获取响应body流的page_url后,遍历整个网页,依次匹配相应的body流,并计算出提取结果。
  2、读取提取结果,将提取结果依次放置到对应的javascript中,并计算出提取值的base64编码。
  
  3、将提取值转换为base64编码的javascript文件。根据base64编码结果,可以计算出被提取的图片链接。
  二、提取规则总体思路:从0开始,给重定向http头匹配正则表达式,计算出匹配率,通过http头约束,根据不同的匹配率分配不同的抓取规则,将匹配链接中的内容提取。例如:匹配率低于70%时,则不进行抓取。只抓取匹配率达到70%以上的规则,将该规则提取出来。
  1、正则提取匹配率http头规则::正则表达式匹配上限:500^^$一次通用问题的目标链接:/input/a#innerhtml匹配率500%*imgfor://user-agent:''*imgfor://user-agent:''*server:''*input://source=''*offset://http/input*img://user-agent:''*input://user-agent:''*text://user-agent:''*input://user-agent:''*input://inputis://(site:''*)*regexp://*sites://***。

js提取指定网站内容用php提取网页源代码用xpath解析

网站优化优采云 发表了文章 • 0 个评论 • 91 次浏览 • 2022-09-04 15:02 • 来自相关话题

  js提取指定网站内容用php提取网页源代码用xpath解析
  js提取指定网站内容
  用php提取网页源代码用xpath解析找到目标字符串
  用.eval('%(div[0].class)')会跳转到任意代码,
  fasterxml2包里面有php提取字符串的包。在不输出网页css的情况下,就可以提取字符串。也可以用专门的php提取器。
  
  php里面有这种php相关的提取器。用eval或者xpath找到你需要的那行就可以了。
  excel模板里面都是以xml文件存储的,提取这样文件中的xml,然后用php读取。要提取php中的xml文件,可以用phplr读取。
  提取视频?那就用asp脚本呗
  fasterxml2包里就有php提取,asp、python和php版本都有。
  
  activex也有的呢
  activex有php提取服务
  php可以用phplr程序正则表达式比较并查找对应字符串用activex文件属性设置runtime=nibyg.php
  强烈推荐金山搜狗输入法的导航包不用自己写php文件模板,用它自带的php提取功能就可以了如果要自己写文件提取代码,
  mysql的userdatabase就可以提取数据库,而且导出数据库配置,不过需要连接数据库;laravel不知道能不能, 查看全部

  js提取指定网站内容用php提取网页源代码用xpath解析
  js提取指定网站内容
  用php提取网页源代码用xpath解析找到目标字符串
  用.eval('%(div[0].class)')会跳转到任意代码,
  fasterxml2包里面有php提取字符串的包。在不输出网页css的情况下,就可以提取字符串。也可以用专门的php提取器。
  
  php里面有这种php相关的提取器。用eval或者xpath找到你需要的那行就可以了。
  excel模板里面都是以xml文件存储的,提取这样文件中的xml,然后用php读取。要提取php中的xml文件,可以用phplr读取。
  提取视频?那就用asp脚本呗
  fasterxml2包里就有php提取,asp、python和php版本都有。
  
  activex也有的呢
  activex有php提取服务
  php可以用phplr程序正则表达式比较并查找对应字符串用activex文件属性设置runtime=nibyg.php
  强烈推荐金山搜狗输入法的导航包不用自己写php文件模板,用它自带的php提取功能就可以了如果要自己写文件提取代码,
  mysql的userdatabase就可以提取数据库,而且导出数据库配置,不过需要连接数据库;laravel不知道能不能,

web前端工程师js提取指定网站内容抓取

网站优化优采云 发表了文章 • 0 个评论 • 91 次浏览 • 2022-08-21 06:02 • 来自相关话题

  web前端工程师js提取指定网站内容抓取
  js提取指定网站内容抓取(),抓取互联网的内容,包括静态文件和二进制文件。js提取指定网站内容可以抓取的格式不限,支持,网页,js文件,图片,网页指定区域的文本,
  javascript写法或者看下这个javascript抓取网站数据javascript抓取网站数据源码_javascript教程
  
  如果有空的话,或者确实有兴趣,可以来我这边做一个二进制文件的提取啊,
  对于我自己来说用到的就是es6:*.js*.xml*.json*.jsx
  
  js提取有很多方式,比如结构化关键字提取、文本提取、链接提取等,在目前的web前端工程师工作的角色是一个全栈开发工程师,他们的工作对于js的要求主要是三个方面,首先是兼容性,因为js还存在各种限制与兼容问题,但目前很多公司为了节省成本一般只要求实现页面的功能就可以了,这样就会对页面交互和输入输出内容有大量需求,这样就对页面内容、数据结构、排序等逻辑方面的要求提出要求。
  第二是性能问题,一个页面要同时显示很多的数据,我们可以把页面做一些拆分,也就是分区域显示,页面拆分也就成为分区域绘制等,原本很耗时的事情js可以快速完成,这样就要求页面更加简洁。第三是逻辑方面,页面中有大量的表单元素,每个表单都有类似于选择框的选择逻辑等,如果做一个模块一个模块的提取并处理所有相关表单数据,就会导致性能与一致性问题。
  对于全栈工程师来说,一个web前端工程师要根据项目对性能有硬性要求,例如几个月的工作是否在实际项目中有明显的提升等,有很多全栈开发工程师会选择使用node.js作为后端框架来实现前端框架,从而减少对前端性能的压力,而且可以加快代码在主机上的可重用性。最后结论是,前端工程师当全栈工程师比较好,因为工作量降低了对性能和一致性等方面会得到改善。 查看全部

  web前端工程师js提取指定网站内容抓取
  js提取指定网站内容抓取(),抓取互联网的内容,包括静态文件和二进制文件。js提取指定网站内容可以抓取的格式不限,支持,网页,js文件,图片,网页指定区域的文本,
  javascript写法或者看下这个javascript抓取网站数据javascript抓取网站数据源码_javascript教程
  
  如果有空的话,或者确实有兴趣,可以来我这边做一个二进制文件的提取啊,
  对于我自己来说用到的就是es6:*.js*.xml*.json*.jsx
  
  js提取有很多方式,比如结构化关键字提取、文本提取、链接提取等,在目前的web前端工程师工作的角色是一个全栈开发工程师,他们的工作对于js的要求主要是三个方面,首先是兼容性,因为js还存在各种限制与兼容问题,但目前很多公司为了节省成本一般只要求实现页面的功能就可以了,这样就会对页面交互和输入输出内容有大量需求,这样就对页面内容、数据结构、排序等逻辑方面的要求提出要求。
  第二是性能问题,一个页面要同时显示很多的数据,我们可以把页面做一些拆分,也就是分区域显示,页面拆分也就成为分区域绘制等,原本很耗时的事情js可以快速完成,这样就要求页面更加简洁。第三是逻辑方面,页面中有大量的表单元素,每个表单都有类似于选择框的选择逻辑等,如果做一个模块一个模块的提取并处理所有相关表单数据,就会导致性能与一致性问题。
  对于全栈工程师来说,一个web前端工程师要根据项目对性能有硬性要求,例如几个月的工作是否在实际项目中有明显的提升等,有很多全栈开发工程师会选择使用node.js作为后端框架来实现前端框架,从而减少对前端性能的压力,而且可以加快代码在主机上的可重用性。最后结论是,前端工程师当全栈工程师比较好,因为工作量降低了对性能和一致性等方面会得到改善。

js提取指定网站内容是什么?js怎么获取指定内容

网站优化优采云 发表了文章 • 0 个评论 • 94 次浏览 • 2022-08-20 01:01 • 来自相关话题

  js提取指定网站内容是什么?js怎么获取指定内容
  js提取指定网站内容的指定dom,获取到指定网站指定的url,获取指定网站不同指定事件的function,获取指定网站的所有段,保存到你自己存放dom的数据库中。
  mw查看内部数据库的方法:googleapisandsomeinstantgetapis:
  
  可以通过直接调用mw.list_string方法来获取相关网站的全局数据,然后用on获取你想获取的指定内容的dom节点,这个dom节点直接指向你的一级页面src指向的锚点。这样on获取到的指定字符串就是你想要获取的内容,再写入到数据库。
  js是调用的mw提供的api.list_string
  
  开发语言vs.平台,我倾向于前者,你这个问题的情景说起来挺好,有个前提你自己得知道自己研究的这个语言是一个什么样的语言,否则你很难再整个整个js领域中摸出个所以然来,另外就是不要把nodejs的我记得是叫npm这么一段代码库放在package.json中,而应该放在.vue或者.vuex这种后端平台对应的react或者express代码中,避免一个在后端服务器对应的开发环境和一个前端服务器对应的开发环境混淆。
  目测1.是这些页面还有文件夹2.是网页本身代码获取一页详细资料4.肯定有一个node服务器
  网页源码中list_string字段,前面有个url图标,进入页面时在nodewindow窗口下打开命令npminstall-gjquery即可。 查看全部

  js提取指定网站内容是什么?js怎么获取指定内容
  js提取指定网站内容的指定dom,获取到指定网站指定的url,获取指定网站不同指定事件的function,获取指定网站的所有段,保存到你自己存放dom的数据库中。
  mw查看内部数据库的方法:googleapisandsomeinstantgetapis:
  
  可以通过直接调用mw.list_string方法来获取相关网站的全局数据,然后用on获取你想获取的指定内容的dom节点,这个dom节点直接指向你的一级页面src指向的锚点。这样on获取到的指定字符串就是你想要获取的内容,再写入到数据库。
  js是调用的mw提供的api.list_string
  
  开发语言vs.平台,我倾向于前者,你这个问题的情景说起来挺好,有个前提你自己得知道自己研究的这个语言是一个什么样的语言,否则你很难再整个整个js领域中摸出个所以然来,另外就是不要把nodejs的我记得是叫npm这么一段代码库放在package.json中,而应该放在.vue或者.vuex这种后端平台对应的react或者express代码中,避免一个在后端服务器对应的开发环境和一个前端服务器对应的开发环境混淆。
  目测1.是这些页面还有文件夹2.是网页本身代码获取一页详细资料4.肯定有一个node服务器
  网页源码中list_string字段,前面有个url图标,进入页面时在nodewindow窗口下打开命令npminstall-gjquery即可。

js提取指定网站内容的页面进行爬取简单易用

网站优化优采云 发表了文章 • 0 个评论 • 96 次浏览 • 2022-08-18 22:06 • 来自相关话题

  js提取指定网站内容的页面进行爬取简单易用
  js提取指定网站内容的页面进行爬取,抓取的数据直接保存在网站数据库中,简单易用。下面我们就通过一个实例来分析js提取json数据。
  好像有些网站直接返回html,看那个语言能写了。
  
  js提取json数据是一个很蛋疼的事情。json提取出来放到数据库里是一堆没有意义的东西。所以干脆不应该给数据提取出来。而是好好想想如何设计一个简单、高效的检索结构。另外一个比较好的办法就是用比如setdata做一些映射操作,另外这些操作采用workflow来操作很合理,另外可以完全在本地操作。
  jsoncurl这个库有js代码,
  简单来说,可以借助一些工具来提取,然后转换成json。我比较喜欢torbir这个库提供的workflow。
  
  我觉得楼上写的很详细了,我来说一下我遇到的问题,然后我的方法和结果w3cschool:js提取xxx以xxx作为key-value就可以转成json了torbir:中文乱码、区分小写-->advent+key-valueonly关键点:想象一下要解析的url有什么样的组成,有哪些字段,然后一个一个进行处理,然后一点一点output到数据库。
  requests+requestslib/requests
  这是一个快速开发爬虫的一个很不错的库github-eternalfool/cuttera:apythonthatlookssoimportantincuttingjson. 查看全部

  js提取指定网站内容的页面进行爬取简单易用
  js提取指定网站内容的页面进行爬取,抓取的数据直接保存在网站数据库中,简单易用。下面我们就通过一个实例来分析js提取json数据。
  好像有些网站直接返回html,看那个语言能写了。
  
  js提取json数据是一个很蛋疼的事情。json提取出来放到数据库里是一堆没有意义的东西。所以干脆不应该给数据提取出来。而是好好想想如何设计一个简单、高效的检索结构。另外一个比较好的办法就是用比如setdata做一些映射操作,另外这些操作采用workflow来操作很合理,另外可以完全在本地操作。
  jsoncurl这个库有js代码,
  简单来说,可以借助一些工具来提取,然后转换成json。我比较喜欢torbir这个库提供的workflow。
  
  我觉得楼上写的很详细了,我来说一下我遇到的问题,然后我的方法和结果w3cschool:js提取xxx以xxx作为key-value就可以转成json了torbir:中文乱码、区分小写-->advent+key-valueonly关键点:想象一下要解析的url有什么样的组成,有哪些字段,然后一个一个进行处理,然后一点一点output到数据库。
  requests+requestslib/requests
  这是一个快速开发爬虫的一个很不错的库github-eternalfool/cuttera:apythonthatlookssoimportantincuttingjson.

js提取指定网站内容(表格、图片等)是什么?

网站优化优采云 发表了文章 • 0 个评论 • 78 次浏览 • 2022-08-18 19:03 • 来自相关话题

  js提取指定网站内容(表格、图片等)是什么?
  js提取指定网站内容(表格、图片等)html,xml转换js,css都可以,适合已有模板情况下,节省网站构建。和jquery,bootstrap搭配的更和谐。
  看你只提取哪一个类别吧?是图片?是网页文本?要做效果的话,现在还有一些可以和js搭配使用的方法,但是基本上都是“模块化”的,有限的js方面调整,写哪个页面就改哪个页面里面的内容而已,可以节省大量的工作量,但是有的就要修改很多次。
  
  网站页面分三类:html模板、js和css文件。如果只是提取首页的html文件就好办了。关键是写好各个部分的模板。组装方面就很难做了,需要熟悉jquery或者google的sass。不可能把所有东西都封装成js,结构上和设计上的差异还是有的。在特定的场景下需要考虑的地方比较多。
  高版本的浏览器可以设置sourcemode属性的。还有就是,你大概也不会特意设置加载模板文件的。
  高版本的浏览器都是不支持这个东西的。
  
  对方的js肯定和我一样是拿脚本写的
  如果版本低,估计需要重写js部分。版本高的版本可以写脚本。
  我也是设计师,拿我自己的经验说一下:不建议使用js提取数据可能要拼接,很麻烦。直接改html文件内容便可,可以简化js部分。
  把页面拆分,各个模块改来改去就可以了,尽量用前后端控制,如果页面不大, 查看全部

  js提取指定网站内容(表格、图片等)是什么?
  js提取指定网站内容(表格、图片等)html,xml转换js,css都可以,适合已有模板情况下,节省网站构建。和jquery,bootstrap搭配的更和谐。
  看你只提取哪一个类别吧?是图片?是网页文本?要做效果的话,现在还有一些可以和js搭配使用的方法,但是基本上都是“模块化”的,有限的js方面调整,写哪个页面就改哪个页面里面的内容而已,可以节省大量的工作量,但是有的就要修改很多次。
  
  网站页面分三类:html模板、js和css文件。如果只是提取首页的html文件就好办了。关键是写好各个部分的模板。组装方面就很难做了,需要熟悉jquery或者google的sass。不可能把所有东西都封装成js,结构上和设计上的差异还是有的。在特定的场景下需要考虑的地方比较多。
  高版本的浏览器可以设置sourcemode属性的。还有就是,你大概也不会特意设置加载模板文件的。
  高版本的浏览器都是不支持这个东西的。
  
  对方的js肯定和我一样是拿脚本写的
  如果版本低,估计需要重写js部分。版本高的版本可以写脚本。
  我也是设计师,拿我自己的经验说一下:不建议使用js提取数据可能要拼接,很麻烦。直接改html文件内容便可,可以简化js部分。
  把页面拆分,各个模块改来改去就可以了,尽量用前后端控制,如果页面不大,

js提取指定网站内容,包括图片、数据、视频等

网站优化优采云 发表了文章 • 0 个评论 • 225 次浏览 • 2022-08-07 16:00 • 来自相关话题

  js提取指定网站内容,包括图片、数据、视频等
  js提取指定网站内容,包括图片、数据、视频等,可以把正文文本提取出来,把正文文本替换成网址,方便加入到图片等数据中。视频音频数据提取比较麻烦。markdown编辑器很少,建议用notepad++,sublimetext2,vim等,免费软件。yandex.yml,yandex.markdown是国内开发的,比较简单,基本html和flash页面都可以替换,用户体验较好。使用chrome打开网站,安装webpack,打开console,输入你需要的参数。
  提取微信文章里的图片?
  可以用markdown编辑器,把文章内容提取出来,
  
  youtube的articlemanager,
  yahooprime的图片提取工具javascriptwebglstudio可以提取微信上所有的图片:
  更快捷的方法:yahooprime自带sourcearticle功能,
  
  最好是用浏览器插件来解决,安装对应的浏览器扩展程序,然后保存,再选择解压到想要的目录。mac上:chrome浏览器的「扩展程序」页面,有些mac上已经有对应的扩展程序;firefox的扩展程序网站,有些有,
  这个很有用的owasp的html5工具,推荐使用gochrome的,
  如果是从html转换成html5的,比如你是要从html的内容转换成js、css、sass等是应该可以的,html5工具网站很多比如:html5icons(javascript/cssicons)如果需要从html转换成css可以用jemarketforever再说也可以上bootstrap官网看看的css能做些什么:,你总是可以找到的对吧,就是看你的技术能力了。
  html5exchange推荐一个qa:exchangevs.quickpatch支持的工具就更多了。不同工具实现功能差别蛮大的,必须具体需求才能区分哪个好哪个不好。 查看全部

  js提取指定网站内容,包括图片、数据、视频等
  js提取指定网站内容,包括图片、数据、视频等,可以把正文文本提取出来,把正文文本替换成网址,方便加入到图片等数据中。视频音频数据提取比较麻烦。markdown编辑器很少,建议用notepad++,sublimetext2,vim等,免费软件。yandex.yml,yandex.markdown是国内开发的,比较简单,基本html和flash页面都可以替换,用户体验较好。使用chrome打开网站,安装webpack,打开console,输入你需要的参数。
  提取微信文章里的图片?
  可以用markdown编辑器,把文章内容提取出来,
  
  youtube的articlemanager,
  yahooprime的图片提取工具javascriptwebglstudio可以提取微信上所有的图片:
  更快捷的方法:yahooprime自带sourcearticle功能,
  
  最好是用浏览器插件来解决,安装对应的浏览器扩展程序,然后保存,再选择解压到想要的目录。mac上:chrome浏览器的「扩展程序」页面,有些mac上已经有对应的扩展程序;firefox的扩展程序网站,有些有,
  这个很有用的owasp的html5工具,推荐使用gochrome的,
  如果是从html转换成html5的,比如你是要从html的内容转换成js、css、sass等是应该可以的,html5工具网站很多比如:html5icons(javascript/cssicons)如果需要从html转换成css可以用jemarketforever再说也可以上bootstrap官网看看的css能做些什么:,你总是可以找到的对吧,就是看你的技术能力了。
  html5exchange推荐一个qa:exchangevs.quickpatch支持的工具就更多了。不同工具实现功能差别蛮大的,必须具体需求才能区分哪个好哪个不好。

js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api

网站优化优采云 发表了文章 • 0 个评论 • 93 次浏览 • 2022-07-26 20:08 • 来自相关话题

  js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api
  js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api去爬虫别人提取网站内容一样,这个web视频是在chrome的开发者工具里,用的是抓包方式提取网页内容,会发现抓包的过程中是加密的。一、加密方式:一种简单粗暴的方式是,直接把网页内容的域名解析出来然后把加密的html的内容生成js的代码供浏览器解析,如下图,这种方式适合一些必须通过https通道进行交互的场景。
  
  另一种方式是,利用反向代理,把普通的代理服务器伪装成浏览器进行访问,目前百度的代理加速还是不错的,做成一个域名绑定的解析js代码,利用https通道进行跨越代理访问,或者做一个反向代理服务器绑定一个静态站点,用这个静态站点做代理访问的代理服务器伪装成浏览器来解析加密html,如下图,这种方式只适合解析带有指定链接的文章。
  
  二、源码格式:对于没有url结构的文章,可以考虑将网页源码生成url结构,对一些内容较多的文章可以根据网页包含的关键词提取关键信息,如下图,可以提取“婚纱摄影“所对应的url结构。不同层级的站点(网站),网页结构都可以做一些定制,比如生成出树状的结构,非结构化文件提取更加容易,不同页面能够在最短的时间内提取出大部分信息。
  比如知乎的首页,知乎上包含了很多话题,可以将这些结构化的东西抽象成树状的组织结构,或者做成文件夹的方式来生成树状结构,方便提取,抽象方式如下图,抽象的树状结构如下图,抽象树状结构这种方式适合抽象较少的文件的文章内容,比如歌曲名称和歌曲存档等等。当然可以直接定制一个所有的页面的定制过程,构建api库,来抽象一些url结构,抽象一些关键词,但是代码量比较大。---欢迎大家关注我的公众号:【程序人生】。这里有和大家分享一些高效学习的方法和干货。 查看全部

  js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api
  js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api去爬虫别人提取网站内容一样,这个web视频是在chrome的开发者工具里,用的是抓包方式提取网页内容,会发现抓包的过程中是加密的。一、加密方式:一种简单粗暴的方式是,直接把网页内容的域名解析出来然后把加密的html的内容生成js的代码供浏览器解析,如下图,这种方式适合一些必须通过https通道进行交互的场景。
  
  另一种方式是,利用反向代理,把普通的代理服务器伪装成浏览器进行访问,目前百度的代理加速还是不错的,做成一个域名绑定的解析js代码,利用https通道进行跨越代理访问,或者做一个反向代理服务器绑定一个静态站点,用这个静态站点做代理访问的代理服务器伪装成浏览器来解析加密html,如下图,这种方式只适合解析带有指定链接的文章。
  
  二、源码格式:对于没有url结构的文章,可以考虑将网页源码生成url结构,对一些内容较多的文章可以根据网页包含的关键词提取关键信息,如下图,可以提取“婚纱摄影“所对应的url结构。不同层级的站点(网站),网页结构都可以做一些定制,比如生成出树状的结构,非结构化文件提取更加容易,不同页面能够在最短的时间内提取出大部分信息。
  比如知乎的首页,知乎上包含了很多话题,可以将这些结构化的东西抽象成树状的组织结构,或者做成文件夹的方式来生成树状结构,方便提取,抽象方式如下图,抽象的树状结构如下图,抽象树状结构这种方式适合抽象较少的文件的文章内容,比如歌曲名称和歌曲存档等等。当然可以直接定制一个所有的页面的定制过程,构建api库,来抽象一些url结构,抽象一些关键词,但是代码量比较大。---欢迎大家关注我的公众号:【程序人生】。这里有和大家分享一些高效学习的方法和干货。

js提取指定网站内容提取robots.txt文件可实现更多功能

网站优化优采云 发表了文章 • 0 个评论 • 96 次浏览 • 2022-07-22 07:03 • 来自相关话题

  js提取指定网站内容提取robots.txt文件可实现更多功能
  
  js提取指定网站内容,wordpress提取指定网站内容相比之下,wordpress提取robots.txt文件可实现更多的功能。同时还可以根据网站类型,提取性能更佳。网站提取网站内容基本分两种。一种是提取主题代码。一种是提取控制器代码。二者区别如下:1.提取控制器主要原理:在控制器后面生成一个.img标签,上面有网站首页的url,然后写入.html格式的文件中。
  
  2.提取主题提取主题,比较常见的方法就是使用网站模板提取首页:在本地生成这个主题的.html文件,上传到last.php到last.php中。如下:这样,就生成了主题的html页面。这样在网站后台,就可以提取到首页的内容。当然,上图中使用了反向代理,如果不需要代理,或代理地址为空,则无法提取。另外也可以使用网站的二级域名对应的主题二级域名对应的主题为。如下:我这里使用二级域名查询,也可以查询一级域名对应的主题页面。
  第一步,首先,在你的wordpress网站,运行一个插件,基于wordpress新增一个host,这个主机名,如,安装这个插件,手动设置,并记录。第二步,运行第一步实现的host后,将baiduspider设置路径指向:../wordpress/wp-content.php第三步,将测试获取的内容导出到excel第四步,在你测试的网站下,直接操作,就可以读取数据了。例如,你测试了test的文章,那么在test这个主题的host中,就可以查到主题的源代码文件。 查看全部

  js提取指定网站内容提取robots.txt文件可实现更多功能
  
  js提取指定网站内容,wordpress提取指定网站内容相比之下,wordpress提取robots.txt文件可实现更多的功能。同时还可以根据网站类型,提取性能更佳。网站提取网站内容基本分两种。一种是提取主题代码。一种是提取控制器代码。二者区别如下:1.提取控制器主要原理:在控制器后面生成一个.img标签,上面有网站首页的url,然后写入.html格式的文件中。
  
  2.提取主题提取主题,比较常见的方法就是使用网站模板提取首页:在本地生成这个主题的.html文件,上传到last.php到last.php中。如下:这样,就生成了主题的html页面。这样在网站后台,就可以提取到首页的内容。当然,上图中使用了反向代理,如果不需要代理,或代理地址为空,则无法提取。另外也可以使用网站的二级域名对应的主题二级域名对应的主题为。如下:我这里使用二级域名查询,也可以查询一级域名对应的主题页面。
  第一步,首先,在你的wordpress网站,运行一个插件,基于wordpress新增一个host,这个主机名,如,安装这个插件,手动设置,并记录。第二步,运行第一步实现的host后,将baiduspider设置路径指向:../wordpress/wp-content.php第三步,将测试获取的内容导出到excel第四步,在你测试的网站下,直接操作,就可以读取数据了。例如,你测试了test的文章,那么在test这个主题的host中,就可以查到主题的源代码文件。

js提取指定网站内容并保存至数据库提取内容内容

网站优化优采云 发表了文章 • 0 个评论 • 83 次浏览 • 2022-07-18 07:05 • 来自相关话题

  js提取指定网站内容并保存至数据库提取内容内容
  js提取指定网站内容并保存至数据库提取网站内容并存入数据库
  1.用一些好用的web工具,
  看到一篇文章,觉得写的很好,
  
  重点:javascript
  可以使用一些浏览器脚本
  ssr这种东西,都看不到自己的服务器端实现的方法,岂不就是拿无知开涮,
  不看你网站文档,
  
  ajax这种东西都看不到自己的服务器端实现的方法,岂不就是拿无知开涮,拿没开发过的东西开涮?web前端培训这么火,很多没写过网站的都在培训网站了,谁能想到这种东西竟然也有培训?自己没把握好,来这问,不如问专业的前端程序员。
  单页应用,三层form,点击通过表单等通道触发处理。
  还是你不懂计算机,没有扎实的基础,写不了一个稳定的web应用,你就算搞出来也是扯淡。
  经常看到web前端,所谓phpweb前端开发,就是用php写一个页面,web后端有java,go等,再写一套自己的后端代码去测试上线。另外那句话用在你身上没问题,但是你应该去问java,php,go等前端开发的人,他们应该比你懂的多。至于你应该从哪学习,你应该自己去看看怎么去搞web前端才不扯淡。 查看全部

  js提取指定网站内容并保存至数据库提取内容内容
  js提取指定网站内容并保存至数据库提取网站内容并存入数据库
  1.用一些好用的web工具,
  看到一篇文章,觉得写的很好,
  
  重点:javascript
  可以使用一些浏览器脚本
  ssr这种东西,都看不到自己的服务器端实现的方法,岂不就是拿无知开涮,
  不看你网站文档,
  
  ajax这种东西都看不到自己的服务器端实现的方法,岂不就是拿无知开涮,拿没开发过的东西开涮?web前端培训这么火,很多没写过网站的都在培训网站了,谁能想到这种东西竟然也有培训?自己没把握好,来这问,不如问专业的前端程序员。
  单页应用,三层form,点击通过表单等通道触发处理。
  还是你不懂计算机,没有扎实的基础,写不了一个稳定的web应用,你就算搞出来也是扯淡。
  经常看到web前端,所谓phpweb前端开发,就是用php写一个页面,web后端有java,go等,再写一套自己的后端代码去测试上线。另外那句话用在你身上没问题,但是你应该去问java,php,go等前端开发的人,他们应该比你懂的多。至于你应该从哪学习,你应该自己去看看怎么去搞web前端才不扯淡。

js提取指定网站内容是怎么做的?js怎么提取

网站优化优采云 发表了文章 • 0 个评论 • 210 次浏览 • 2022-07-16 07:03 • 来自相关话题

  js提取指定网站内容是怎么做的?js怎么提取
  js提取指定网站内容一直是我想实现的,但是只是执行js写的。其实也可以用http协议下发一个指定链接,然后js进行获取,但是这样做对于大多数网站来说要在需要获取js的网站连接域名有域名才可以。后来我用tiobe排名的时候,发现chrome非常难找,没有查询完全页的cannonic浏览器,是没有对应浏览器。
  
  于是考虑js爬虫+requests+selenium+shell就可以全自动的抓取。为了获取一个html页面,首先需要抓取一个html页面,然后要将其下载下来。通过百度找到这个页面,进行如下操作:1.单击页面上方“访问页面”,获取index.html并解析成为一个xml2.打开浏览器的开发者工具,在地址栏中打开xml文件,进行解析.3.在executable内外抓取相应的页面,并将抓取出来的executable复制到浏览器地址栏,获取页面内容文件。
  4.将获取好的js文件添加到浏览器中,正常页面会在下一个文件中。整个操作过程最长两分钟左右。然后获取的html将直接存储到js文件中。后来发现js文件打开比较慢,我们还需要使用正则表达式才能找到相应的页面,以下代码就是进行正则表达式匹配,来得到页面。1.打开页面,鼠标右键选择检查,,然后选择以页面中的元素为中心(包括标题,文字,img,footer,iframe等)点击菜单:network->pages,右键->匹配正则,命名搜索出来的文件内容中匹配页面中任意一个条件为字符串的文件,也可以自己选择executable下复制的文件夹名。
  
  一般情况下页面都有几十上百个,加上文件名的条件,也有上千条左右。2.找到和我们想要匹配出来文件的文件名,再放进pages中(以页面中的index.html为例)functiongetheaderpagescontext(pagescontext){for(letline:pagescontext){if(line.startswith("\n")&&line.startswith("\n")){returnnull;}}return0;}正则匹配案例3.如果拿到pagesoftend中的内容:我们只需要通过正则表达式找到页面中的xhtml文件后缀,然后匹配相应的文件,保存相应的文件,再将此文件放到浏览器的开发者工具的文件夹目录下,就能获取该网页的更多内容。
  将找到的xhtml内容内容保存到.exe文件中以后,我们可以修改后缀名。修改时有个原则,即每次都需要知道这个网页最后标签名的后缀。如果代码写得足够优美的话,代码可以非常简洁,但是为了快速,这是必须。重新思考下代码,代码如下:.exe-p-i-f.unkeys.submodule.index.htmlindex.html其实代码就是重复getheaderpagescontext(pagescont。 查看全部

  js提取指定网站内容是怎么做的?js怎么提取
  js提取指定网站内容一直是我想实现的,但是只是执行js写的。其实也可以用http协议下发一个指定链接,然后js进行获取,但是这样做对于大多数网站来说要在需要获取js的网站连接域名有域名才可以。后来我用tiobe排名的时候,发现chrome非常难找,没有查询完全页的cannonic浏览器,是没有对应浏览器。
  
  于是考虑js爬虫+requests+selenium+shell就可以全自动的抓取。为了获取一个html页面,首先需要抓取一个html页面,然后要将其下载下来。通过百度找到这个页面,进行如下操作:1.单击页面上方“访问页面”,获取index.html并解析成为一个xml2.打开浏览器的开发者工具,在地址栏中打开xml文件,进行解析.3.在executable内外抓取相应的页面,并将抓取出来的executable复制到浏览器地址栏,获取页面内容文件。
  4.将获取好的js文件添加到浏览器中,正常页面会在下一个文件中。整个操作过程最长两分钟左右。然后获取的html将直接存储到js文件中。后来发现js文件打开比较慢,我们还需要使用正则表达式才能找到相应的页面,以下代码就是进行正则表达式匹配,来得到页面。1.打开页面,鼠标右键选择检查,,然后选择以页面中的元素为中心(包括标题,文字,img,footer,iframe等)点击菜单:network->pages,右键->匹配正则,命名搜索出来的文件内容中匹配页面中任意一个条件为字符串的文件,也可以自己选择executable下复制的文件夹名。
  
  一般情况下页面都有几十上百个,加上文件名的条件,也有上千条左右。2.找到和我们想要匹配出来文件的文件名,再放进pages中(以页面中的index.html为例)functiongetheaderpagescontext(pagescontext){for(letline:pagescontext){if(line.startswith("\n")&&line.startswith("\n")){returnnull;}}return0;}正则匹配案例3.如果拿到pagesoftend中的内容:我们只需要通过正则表达式找到页面中的xhtml文件后缀,然后匹配相应的文件,保存相应的文件,再将此文件放到浏览器的开发者工具的文件夹目录下,就能获取该网页的更多内容。
  将找到的xhtml内容内容保存到.exe文件中以后,我们可以修改后缀名。修改时有个原则,即每次都需要知道这个网页最后标签名的后缀。如果代码写得足够优美的话,代码可以非常简洁,但是为了快速,这是必须。重新思考下代码,代码如下:.exe-p-i-f.unkeys.submodule.index.htmlindex.html其实代码就是重复getheaderpagescontext(pagescont。

js提取指定网站内容-上海怡诺唐咨询公司

网站优化优采云 发表了文章 • 0 个评论 • 80 次浏览 • 2022-07-09 03:00 • 来自相关话题

  js提取指定网站内容-上海怡诺唐咨询公司
  js提取指定网站内容然后拼接成一个文本的,webpack有一个babel的插件可以提取,jquery也可以提取。用xml提取文本类似,但xml只能一份一份转化,具体对应的格式也有提取。
  所有的东西都可以按我的要求提取出来?我要的是这个网站提取出来,后缀多一个zhihu提取出来。
  
  一般这种情况都是直接拼接成字符串了,比如这个网站。
  有可能是用xml库解析js生成的body之后,js直接就直接component成了一个固定的view/state了吧。可以用xml.loader把js组件转成xml序列格式再转成json(大部分json.parser都是这么干的)。
  @parents关注了这个问题。感觉是obejct数据解析出来的,
  
  用的是xml.parser(看到了第一名的eloquentjs,但是我想了想可能在写法上差了一点)。可以传入值自己配置xmlplugin的类型参数。read:body-{value:string,source:'xml'}document:text-source//don'tchangecontent-type,最好不要试图改写json';em'来解析。
  既然你都打算写解析了为什么还要有这种问题?
  看了某位的回答,我觉得上面有个答案有问题。给你写个例子。你在xml里面输入一串包含"weixin"的数据,点“gitcommit",然后把xml发送给服务器。服务器会处理生成json的数据再解析成"weixin"为你提交的"weixin"这样。但是你打算说的是,在js中用xml.parser读xml数据生成json再发送到服务器,请问有可能生成json再转换成js么?可能是兼容性的问题,但是无论哪种,你的做法毫无必要。我的方法就是在js里面处理json,将它再封装成xml。最终的效果就是把xml变成json。 查看全部

  js提取指定网站内容-上海怡诺唐咨询公司
  js提取指定网站内容然后拼接成一个文本的,webpack有一个babel的插件可以提取,jquery也可以提取。用xml提取文本类似,但xml只能一份一份转化,具体对应的格式也有提取。
  所有的东西都可以按我的要求提取出来?我要的是这个网站提取出来,后缀多一个zhihu提取出来。
  
  一般这种情况都是直接拼接成字符串了,比如这个网站。
  有可能是用xml库解析js生成的body之后,js直接就直接component成了一个固定的view/state了吧。可以用xml.loader把js组件转成xml序列格式再转成json(大部分json.parser都是这么干的)。
  @parents关注了这个问题。感觉是obejct数据解析出来的,
  
  用的是xml.parser(看到了第一名的eloquentjs,但是我想了想可能在写法上差了一点)。可以传入值自己配置xmlplugin的类型参数。read:body-{value:string,source:'xml'}document:text-source//don'tchangecontent-type,最好不要试图改写json';em'来解析。
  既然你都打算写解析了为什么还要有这种问题?
  看了某位的回答,我觉得上面有个答案有问题。给你写个例子。你在xml里面输入一串包含"weixin"的数据,点“gitcommit",然后把xml发送给服务器。服务器会处理生成json的数据再解析成"weixin"为你提交的"weixin"这样。但是你打算说的是,在js中用xml.parser读xml数据生成json再发送到服务器,请问有可能生成json再转换成js么?可能是兼容性的问题,但是无论哪种,你的做法毫无必要。我的方法就是在js里面处理json,将它再封装成xml。最终的效果就是把xml变成json。

如何用 Node.js 和 Elasticsearch 构建搜索引擎

网站优化优采云 发表了文章 • 0 个评论 • 84 次浏览 • 2022-07-02 19:05 • 来自相关话题

  如何用 Node.js 和 Elasticsearch 构建搜索引擎
  数据导入
  在本教程中,我将使用 1000 篇学术论文里的内容,这些内容是根据随机算法逐一生成的,并以 JSON 格式提供,其中的数据格式如下所示:
  JSON 格式中的每个字段如字面意思,无需多余解释,但值得注意的是:由于包含随机生成的文章的全部的内容(大概有100~200个段落),所以并未展示。
  虽然 Elasticsearch 提供了索引(indexing),更新(updating)、删除(deleting)单个数据的方法,但我们采用批量(bulk)接口导入数据,因为批量接口在大型数据集上执行操作的效率更高。
  这里,我们调用函数bulkIndex建立索引,并传入 3 个参数,分别是:索引名 library,类型名library,JSON 数据格式变量 articles。bulkIndex函数自身则通过调用esClient对象的bulk接口实现,bulk 方法包含一个body属性的对象参数,并且每个body属性值是一个包含 2 种操作实体的数组对象。第一个实体是 JSON 格式的操作类型对象,该对象中的index属性决定了操作的类型(本例子是文件索引)、索引名、文件ID。第二个实体则是文件对象本身。
  注意,后续可采用同样的方式,为其他类型文件(如书籍或者报告)添加索引。我们还可以有选择的每个文件分配一个唯一的ID,如果不体统唯一的ID,Elasticsearch 将主动为每个文件分配一个随机的唯一ID。
  假设你已经从代码库中下载了 Elasticsearch 项目代码,在项目根目录下执行如下命令,即可将数据导入至Elasticsearch中:
  检查数据的索引是否准确
  Elasticsearch 最大的特性是接近实时检索,这意味着,一旦文档索引建立完成,1 秒内就可被检索(见这里)。索引一旦建立完成,则可通过运行 indice.js 检查索引信息的准确性(源码链接):
  client 中的cat 对象方法提供当前运行实例的各种信息。其中的 indices 方法列出所有的索引信息,包括每个索引的健康状态、以及占用的磁盘大小。 而其中的 v 选项为 cat方法新增头部响应。
  当运行上面代码段,您会发现,集群的健康状态被不同的颜色标示。其中,红色表示为正常运行的有问题集群;黄色表示集群可运行,但存在告警;绿色表示集群正常运行。在本地运行上面的代码段,您极有可能(取决于您的配置)看到集群的健康状态颜色是黄色,这是因为默认的集群设置包含 5 个节点,但本地运行只有 1 个实例正常运行。鉴于本教程的目的仅局限于 Elasticsearch 指导学习,黄色即可。但在线上环境中,你必须确保集群的健康状态颜色是绿色的。
  动态和自定义映射
  如前所述, Elasticsearch 无模式(schema-free),这意味着,在数据导入之前,您无需定义数据的结构(类似于SQL数据库需要预先定义表结构),Elasticsearch 会主动检测。尽管 Elasticsearch 被定义为无模式,但数据结构上仍有些限制。
  Elasticsearch 以映射的方式引用数据结构。当数据索引建立完成后,如果映射不存在,Elasticsearch 会依次检索 JSON 数据的每个字段,然后基于被字段的类型(type)自动生成映射(mapping)。如果存在该字段的映射,则会确保按照同样的映射规则新增数据。否则直接报错。
  比如:如果{"key1": 12}已经存在,Elasticsearch 自动将字段 key1 映射为长整型。现在如果你尝试通过{"key1": "value1", "key2": "value2"} 检索, 则会直接报错,因为系统预期字段 key1 为长整型。同时,如果通过{"key1": 13, "key2": "value2"} 检索则不会报错,并为字段 key2 新增 string 类型。
  映射不能超出文本的范围,大都数情况下,系统自动生成的映射都可正常运行。
  构建搜索引擎
  一旦完成数据索引,我们就可以开始实现搜索引擎。Elasticsearch提供了一个直观的基于JSON的全搜索查询的结构-Query DSL,定义查询。有许多有用的搜索查询类型,但是在这篇文章中,我们将只看到几个通用的类型。关于Query DSL的完整文章可以在这里看到。
  请记住,我提供了每个展示例子的源码的连接。设置完你的环境和索引测试数据后,你可以下载源码,然后运行在你的机器上运行任何例子。可以通过命令行运行节点filename.js。
  
  返回一个或多个索引的所有记录
  为了执行我们的搜索,我们将使用客户端提供的多种搜索方法。最简单的查询是match_all,它可以返回一个或多个索引的所有的记录。下面的例子显示了我们怎么样获取在一个索引中获取所有存储的记录(源码).
  主要的搜索查询包含在Query对象中。就像我们接下来看到的那样,我们可以添加不同的搜索查询类型到这个对象。我们可以为每一个Query添加一个查询类型的关键字(如match_all),让这个Query成为一个包含搜索选项的对象。由于我们想返回索引的所有记录,所以在这个例子中没有查询选项。
  除了Query对象,搜索体中可以包含其他选项的属性,如size和from。size属性决定了返回记录的数量。如果这个值不存在,默认返回10个记录。from属性决定了返回记录的起始索引,这对分页有用。
  理解查询API的返回结果
  如果你打印搜索API返回结果(上面例子的结果)日志。由于它包含了很多信息,刚开始看起来无所适从。
  在最高级别日志输出里,返回结果中含有took属性,该属性值表示查找结果所用的毫秒数,timed_out只有在最大允许时间内没有找到结果时为true,_shards是不同节点的状态的信息(如果部署的是节点集群),hits是查询结果。
  hits的属性值是一个含有下列属性的对象:
  这十分复杂,但是好消息是一旦你实现了一个提取结果的方法,不管你的搜索查询结果时什么,你都可以使用相同的格式获取结果。
  还需要注意的是Elasticsearch有一个好处是它自动地给每一个匹配记录分配分数,这个分数用来量化文件的关联性,返回结果的顺序默认的按钮分数倒排。在例子中我们使用match_all取回了所有的记录,分数是没有意义的,所有的分数都被计算为1.0。
  匹配含指定字段值的文档
  现在我们看几个更加有趣的例子. 我们可以通过使用 match 关键字查询文档是否与指定的字段值匹配。一个最简单的包含 match 关键字的检索主体代码如下所示:
  如上文所述, 首先通过为查询对象新增一个条目,并指定检索类型,上面示例给的是 match 。然后再检索类型对象里面,申明待检索的文档对象,本例是 title 文档对象。然后再文档对象里面,提供相关检索数据,和 query 属性。我希望你测试过上述示例之后,惊讶于 Elasticsearch 的检索效率。
  上述示例执行成功后,将返回title(标题)字段与任一 query 属性词匹配的所有文档信息。同时还可以参考如下示例,为查询对象附加最小匹配数量条件:
  与该查询匹配的文档 title(标题)字段至少包含上诉指定的 3 个关键词。如果查询关键词少于 3个,那么匹配文档的 title(标题)字段必须包含所有的查询词。Elasticsearch 的另一个有用的功能是fuzziness(模糊匹配).这对于用户输入错误的查询词将非常有用,因为fuzzy(模糊匹配)将发现拼写错误并给出最接近词供选择。对于字符串类型,每个关键字的模糊匹配值是根据算法Levenshtein distance算出的最大允许值。fuzziness(模糊匹配)示例如下所示:
  多个字段搜索
  如果你想在多个字段中搜索,可以使用multi_match搜索类型。除了Query对象中的fields属性外,它同match有点类似。fields属性是需要搜索的字段的集合。这里我们将在title,authors.firstname, 和authors.lastname字段中搜索。
  multi_match查询支持其他搜索属性,如minimum_should_match和fuzziness。Elasticsearch支持使用通配符(如*)匹配字段,那么我们可以使用['title', 'authors.*name']把上面的例子变得更短些。
  匹配一个完整的句子
  Elasticsearch也支持精确的匹配一个输入的句子,而不是在单词级别。这个查询是在普通的match查询上扩展而来,叫做match_phrase。下面是一个match_phrase的例子
  
  联合多个查询
  到目前为止,在例子中我们每次请求只使用了单个查询。然而Elasticsearch允许你联合多个查询。最常用的复合查询是bool,bool查询接受4种关键类型must,should,must_not, 和filter.像它们的名字表示的那样,在查询结果的数据里必须匹配must里的查询,必须不匹配must_not里的查询,如果哪个数据匹配should里的查询,它就会获得高分。每一个提到的元素可以使用查询数组格式接受多个搜索查询。
  下面,我们使用bool查询及一个新的叫做query_string的查询类型。它允许你使用AND或OR写一些比较高级的查询。另外,我们使用了range查询,它可以让我们通过给定的范围的方式去限制一个字段。
  在上面的例子中,查询返回的数据,作者的名包含term1或它们的姓包含term2,并且它们的title含有term3,而且它们不在2011,2012或2013年出版的,还有在body字段里含有给定句子数据将获得高分,并被排列到结果的前面(由于在should从句中的match查询)。
  过滤,聚合,和建议
  除了它先进的搜索功能外,Elasticsearch还提供了其他的功能。接下来,我们再看看其他三个比较常用的功能。
  过滤
  也许,你经常想使用特定的条件凝缩查询结果。Elasticsearch通过filters提供了这样的功能。在我们的文章数据里,假设你的查询返回了几个文章,这些文章是你选择的在5个具体年份发布的文章。你可以简单的从搜索结果中过滤出那些不匹配条件的数据,而不改变查询结果的顺序。
  在bool查询的must从句中,过滤和相同查询之间的不同之处在于,过滤不会影响搜索分数,而must查询会。当查询结果返回并且用户使用给定的条件过滤时,他们不想改变结果的顺序,相反地,他们只想从结果中移除不相关的数据。过滤与搜索的格式一样,但在通常情况下,他们在有明确值的字段上定义,而不是文本字符串上。Elasticsearch推荐通过bool复合查询的filter从句添加过滤。
  继续看上面的例子,假设我们想把搜索结果限制在在2011到2015年之间发布的文章里。这样做,我们只需要在一般搜索查询的filter部分添加range查询。这将会从结果中移除那些不匹配的数据。下面是一个过滤查询的例子
  聚合
  聚合框架会基于一次搜索查询,提供各种聚合数据和统计信息。两个主要的聚合类型是度量和分块, 度量聚合会对一个文档的集合进行持续的跟踪并计算度量,而分块聚合则会进行块的构建,每个块都会跟一个键和一个文档查询条件关联起来。度量聚合的示例有平均值,最小值,最大值,加总值还有计数值。分块聚合的示例有范围、日期范围、直方图以及主题项。对聚合器更加深入的描述可以在这里找到。
  聚合可以放置在一个 aggregations 对象里面,而对象自己则是被直接放到 search 对象体中。在 aggregations 对象里面,每一个键都是由用户赋予一个聚合器的名称。聚合器的类型和其它选项都应该是作为这个键的值而放置的。接下来我们要来看看两个不同类型的聚合器,一个是度量的,一个块的。我们会用度量聚合器来尝试找出数据集合中最小的年份值(也就是最久远的文章),而使用块集合器我要做的就是尝试找出每一个关键词各自出现了多少次。
  在上述示例中,我们将度量聚合器命名为 min_year(也可以是其它名称), 也就是 year 这个域上的 min 类型。块聚合器责备命名为keywords, 就是 keywords 这个域上的 terms 类型。聚合操作的结果被装在了响应消息里的 aggregations 元素里面,更深入一点会发现里面包含了每一个聚合器(这里是 min_year 和 keywords)以及它们的聚合操作结果。 如下是来自这个示例响应消息中的部分内容。
  响应消息中默认最多会有10个块返回。你可以在请求中 filed 的边上加入一个size键来规定返回的块的最大数量。如果你想要接收到所有的块,可以将这个值设置为 0。
  建议
  Elasticsearch 提供了多种可以对输入内容提供替换和补全的关联项推荐器(见文档)。下面将介绍术语和短语推荐器。术语推荐器为每个输入文本中的术语提供关联推荐(如果有的话),而短语推荐器将整个输入文本看做一个短语(与将其拆分成术语对比),然后提供其他短语的推荐(如果有的话)。使用推荐API时,需要调用Node.js client的suggest方法。如下为术语推荐器的示例。
  与其他client的方法相同,在请求体中包含一个index字段指明采用的索引。在body字段中添加查询推荐的文本,然后给每个推荐器一个(包含了聚合对象的)名称(本例中的titleSuggester)。其值指明了推荐器的类型和配置。这里,为title字段使用了术语推荐器,限制最大建议的数量是每个token最多5个(size: 5)。
  建议API返回的数据中包含了对应请求中每一个建议器的key,其值是一个与你输入文本中术语数量相同的一个数组。对于数组中的每一个元素,包含一个options数组,其每个对象的text字段中包含了推荐的文本。如下是上面例子中返回数据的一部分。
  获取短语推荐的时候,采用与上文相同的格式并替换推荐器的类型字段即可。如下的例子中,返回数据将与上例格式相同。
  进一步阅读
  Elasticsearch 提供了许多特性,这些特性远远超出了这一篇文章所能讨论的范围。在这篇文章中,我试图站在一个很高的层次上来解释它的特性,并为你提供可用来进一步学习的合适资源。Elasticsearch是非常可靠的,并且有着出色的表现(我希望你在运行范例时已经注意到了这一点)。再加之不断增长的社区支持,使得Elasticsearch在工业中的应用也在不断增加,尤其是对于需要处理实时数据或大数据的公司。
  学习完这里提供的例子之后,我强烈建议你阅读一些相关文档。文档有两个主要来源,一是Elasticsearch参考及其特性,另外还有一个指南,它更多关注的是具体实现,使用案例以及最佳实践。更多文档和源码信息请点击“阅读原文”。
  END 查看全部

  如何用 Node.js 和 Elasticsearch 构建搜索引擎
  数据导入
  在本教程中,我将使用 1000 篇学术论文里的内容,这些内容是根据随机算法逐一生成的,并以 JSON 格式提供,其中的数据格式如下所示:
  JSON 格式中的每个字段如字面意思,无需多余解释,但值得注意的是:由于包含随机生成的文章的全部的内容(大概有100~200个段落),所以并未展示。
  虽然 Elasticsearch 提供了索引(indexing),更新(updating)、删除(deleting)单个数据的方法,但我们采用批量(bulk)接口导入数据,因为批量接口在大型数据集上执行操作的效率更高。
  这里,我们调用函数bulkIndex建立索引,并传入 3 个参数,分别是:索引名 library,类型名library,JSON 数据格式变量 articles。bulkIndex函数自身则通过调用esClient对象的bulk接口实现,bulk 方法包含一个body属性的对象参数,并且每个body属性值是一个包含 2 种操作实体的数组对象。第一个实体是 JSON 格式的操作类型对象,该对象中的index属性决定了操作的类型(本例子是文件索引)、索引名、文件ID。第二个实体则是文件对象本身。
  注意,后续可采用同样的方式,为其他类型文件(如书籍或者报告)添加索引。我们还可以有选择的每个文件分配一个唯一的ID,如果不体统唯一的ID,Elasticsearch 将主动为每个文件分配一个随机的唯一ID。
  假设你已经从代码库中下载了 Elasticsearch 项目代码,在项目根目录下执行如下命令,即可将数据导入至Elasticsearch中:
  检查数据的索引是否准确
  Elasticsearch 最大的特性是接近实时检索,这意味着,一旦文档索引建立完成,1 秒内就可被检索(见这里)。索引一旦建立完成,则可通过运行 indice.js 检查索引信息的准确性(源码链接):
  client 中的cat 对象方法提供当前运行实例的各种信息。其中的 indices 方法列出所有的索引信息,包括每个索引的健康状态、以及占用的磁盘大小。 而其中的 v 选项为 cat方法新增头部响应。
  当运行上面代码段,您会发现,集群的健康状态被不同的颜色标示。其中,红色表示为正常运行的有问题集群;黄色表示集群可运行,但存在告警;绿色表示集群正常运行。在本地运行上面的代码段,您极有可能(取决于您的配置)看到集群的健康状态颜色是黄色,这是因为默认的集群设置包含 5 个节点,但本地运行只有 1 个实例正常运行。鉴于本教程的目的仅局限于 Elasticsearch 指导学习,黄色即可。但在线上环境中,你必须确保集群的健康状态颜色是绿色的。
  动态和自定义映射
  如前所述, Elasticsearch 无模式(schema-free),这意味着,在数据导入之前,您无需定义数据的结构(类似于SQL数据库需要预先定义表结构),Elasticsearch 会主动检测。尽管 Elasticsearch 被定义为无模式,但数据结构上仍有些限制。
  Elasticsearch 以映射的方式引用数据结构。当数据索引建立完成后,如果映射不存在,Elasticsearch 会依次检索 JSON 数据的每个字段,然后基于被字段的类型(type)自动生成映射(mapping)。如果存在该字段的映射,则会确保按照同样的映射规则新增数据。否则直接报错。
  比如:如果{"key1": 12}已经存在,Elasticsearch 自动将字段 key1 映射为长整型。现在如果你尝试通过{"key1": "value1", "key2": "value2"} 检索, 则会直接报错,因为系统预期字段 key1 为长整型。同时,如果通过{"key1": 13, "key2": "value2"} 检索则不会报错,并为字段 key2 新增 string 类型。
  映射不能超出文本的范围,大都数情况下,系统自动生成的映射都可正常运行。
  构建搜索引擎
  一旦完成数据索引,我们就可以开始实现搜索引擎。Elasticsearch提供了一个直观的基于JSON的全搜索查询的结构-Query DSL,定义查询。有许多有用的搜索查询类型,但是在这篇文章中,我们将只看到几个通用的类型。关于Query DSL的完整文章可以在这里看到。
  请记住,我提供了每个展示例子的源码的连接。设置完你的环境和索引测试数据后,你可以下载源码,然后运行在你的机器上运行任何例子。可以通过命令行运行节点filename.js。
  
  返回一个或多个索引的所有记录
  为了执行我们的搜索,我们将使用客户端提供的多种搜索方法。最简单的查询是match_all,它可以返回一个或多个索引的所有的记录。下面的例子显示了我们怎么样获取在一个索引中获取所有存储的记录(源码).
  主要的搜索查询包含在Query对象中。就像我们接下来看到的那样,我们可以添加不同的搜索查询类型到这个对象。我们可以为每一个Query添加一个查询类型的关键字(如match_all),让这个Query成为一个包含搜索选项的对象。由于我们想返回索引的所有记录,所以在这个例子中没有查询选项。
  除了Query对象,搜索体中可以包含其他选项的属性,如size和from。size属性决定了返回记录的数量。如果这个值不存在,默认返回10个记录。from属性决定了返回记录的起始索引,这对分页有用。
  理解查询API的返回结果
  如果你打印搜索API返回结果(上面例子的结果)日志。由于它包含了很多信息,刚开始看起来无所适从。
  在最高级别日志输出里,返回结果中含有took属性,该属性值表示查找结果所用的毫秒数,timed_out只有在最大允许时间内没有找到结果时为true,_shards是不同节点的状态的信息(如果部署的是节点集群),hits是查询结果。
  hits的属性值是一个含有下列属性的对象:
  这十分复杂,但是好消息是一旦你实现了一个提取结果的方法,不管你的搜索查询结果时什么,你都可以使用相同的格式获取结果。
  还需要注意的是Elasticsearch有一个好处是它自动地给每一个匹配记录分配分数,这个分数用来量化文件的关联性,返回结果的顺序默认的按钮分数倒排。在例子中我们使用match_all取回了所有的记录,分数是没有意义的,所有的分数都被计算为1.0。
  匹配含指定字段值的文档
  现在我们看几个更加有趣的例子. 我们可以通过使用 match 关键字查询文档是否与指定的字段值匹配。一个最简单的包含 match 关键字的检索主体代码如下所示:
  如上文所述, 首先通过为查询对象新增一个条目,并指定检索类型,上面示例给的是 match 。然后再检索类型对象里面,申明待检索的文档对象,本例是 title 文档对象。然后再文档对象里面,提供相关检索数据,和 query 属性。我希望你测试过上述示例之后,惊讶于 Elasticsearch 的检索效率。
  上述示例执行成功后,将返回title(标题)字段与任一 query 属性词匹配的所有文档信息。同时还可以参考如下示例,为查询对象附加最小匹配数量条件:
  与该查询匹配的文档 title(标题)字段至少包含上诉指定的 3 个关键词。如果查询关键词少于 3个,那么匹配文档的 title(标题)字段必须包含所有的查询词。Elasticsearch 的另一个有用的功能是fuzziness(模糊匹配).这对于用户输入错误的查询词将非常有用,因为fuzzy(模糊匹配)将发现拼写错误并给出最接近词供选择。对于字符串类型,每个关键字的模糊匹配值是根据算法Levenshtein distance算出的最大允许值。fuzziness(模糊匹配)示例如下所示:
  多个字段搜索
  如果你想在多个字段中搜索,可以使用multi_match搜索类型。除了Query对象中的fields属性外,它同match有点类似。fields属性是需要搜索的字段的集合。这里我们将在title,authors.firstname, 和authors.lastname字段中搜索。
  multi_match查询支持其他搜索属性,如minimum_should_match和fuzziness。Elasticsearch支持使用通配符(如*)匹配字段,那么我们可以使用['title', 'authors.*name']把上面的例子变得更短些。
  匹配一个完整的句子
  Elasticsearch也支持精确的匹配一个输入的句子,而不是在单词级别。这个查询是在普通的match查询上扩展而来,叫做match_phrase。下面是一个match_phrase的例子
  
  联合多个查询
  到目前为止,在例子中我们每次请求只使用了单个查询。然而Elasticsearch允许你联合多个查询。最常用的复合查询是bool,bool查询接受4种关键类型must,should,must_not, 和filter.像它们的名字表示的那样,在查询结果的数据里必须匹配must里的查询,必须不匹配must_not里的查询,如果哪个数据匹配should里的查询,它就会获得高分。每一个提到的元素可以使用查询数组格式接受多个搜索查询。
  下面,我们使用bool查询及一个新的叫做query_string的查询类型。它允许你使用AND或OR写一些比较高级的查询。另外,我们使用了range查询,它可以让我们通过给定的范围的方式去限制一个字段。
  在上面的例子中,查询返回的数据,作者的名包含term1或它们的姓包含term2,并且它们的title含有term3,而且它们不在2011,2012或2013年出版的,还有在body字段里含有给定句子数据将获得高分,并被排列到结果的前面(由于在should从句中的match查询)。
  过滤,聚合,和建议
  除了它先进的搜索功能外,Elasticsearch还提供了其他的功能。接下来,我们再看看其他三个比较常用的功能。
  过滤
  也许,你经常想使用特定的条件凝缩查询结果。Elasticsearch通过filters提供了这样的功能。在我们的文章数据里,假设你的查询返回了几个文章,这些文章是你选择的在5个具体年份发布的文章。你可以简单的从搜索结果中过滤出那些不匹配条件的数据,而不改变查询结果的顺序。
  在bool查询的must从句中,过滤和相同查询之间的不同之处在于,过滤不会影响搜索分数,而must查询会。当查询结果返回并且用户使用给定的条件过滤时,他们不想改变结果的顺序,相反地,他们只想从结果中移除不相关的数据。过滤与搜索的格式一样,但在通常情况下,他们在有明确值的字段上定义,而不是文本字符串上。Elasticsearch推荐通过bool复合查询的filter从句添加过滤。
  继续看上面的例子,假设我们想把搜索结果限制在在2011到2015年之间发布的文章里。这样做,我们只需要在一般搜索查询的filter部分添加range查询。这将会从结果中移除那些不匹配的数据。下面是一个过滤查询的例子
  聚合
  聚合框架会基于一次搜索查询,提供各种聚合数据和统计信息。两个主要的聚合类型是度量和分块, 度量聚合会对一个文档的集合进行持续的跟踪并计算度量,而分块聚合则会进行块的构建,每个块都会跟一个键和一个文档查询条件关联起来。度量聚合的示例有平均值,最小值,最大值,加总值还有计数值。分块聚合的示例有范围、日期范围、直方图以及主题项。对聚合器更加深入的描述可以在这里找到。
  聚合可以放置在一个 aggregations 对象里面,而对象自己则是被直接放到 search 对象体中。在 aggregations 对象里面,每一个键都是由用户赋予一个聚合器的名称。聚合器的类型和其它选项都应该是作为这个键的值而放置的。接下来我们要来看看两个不同类型的聚合器,一个是度量的,一个块的。我们会用度量聚合器来尝试找出数据集合中最小的年份值(也就是最久远的文章),而使用块集合器我要做的就是尝试找出每一个关键词各自出现了多少次。
  在上述示例中,我们将度量聚合器命名为 min_year(也可以是其它名称), 也就是 year 这个域上的 min 类型。块聚合器责备命名为keywords, 就是 keywords 这个域上的 terms 类型。聚合操作的结果被装在了响应消息里的 aggregations 元素里面,更深入一点会发现里面包含了每一个聚合器(这里是 min_year 和 keywords)以及它们的聚合操作结果。 如下是来自这个示例响应消息中的部分内容。
  响应消息中默认最多会有10个块返回。你可以在请求中 filed 的边上加入一个size键来规定返回的块的最大数量。如果你想要接收到所有的块,可以将这个值设置为 0。
  建议
  Elasticsearch 提供了多种可以对输入内容提供替换和补全的关联项推荐器(见文档)。下面将介绍术语和短语推荐器。术语推荐器为每个输入文本中的术语提供关联推荐(如果有的话),而短语推荐器将整个输入文本看做一个短语(与将其拆分成术语对比),然后提供其他短语的推荐(如果有的话)。使用推荐API时,需要调用Node.js client的suggest方法。如下为术语推荐器的示例。
  与其他client的方法相同,在请求体中包含一个index字段指明采用的索引。在body字段中添加查询推荐的文本,然后给每个推荐器一个(包含了聚合对象的)名称(本例中的titleSuggester)。其值指明了推荐器的类型和配置。这里,为title字段使用了术语推荐器,限制最大建议的数量是每个token最多5个(size: 5)。
  建议API返回的数据中包含了对应请求中每一个建议器的key,其值是一个与你输入文本中术语数量相同的一个数组。对于数组中的每一个元素,包含一个options数组,其每个对象的text字段中包含了推荐的文本。如下是上面例子中返回数据的一部分。
  获取短语推荐的时候,采用与上文相同的格式并替换推荐器的类型字段即可。如下的例子中,返回数据将与上例格式相同。
  进一步阅读
  Elasticsearch 提供了许多特性,这些特性远远超出了这一篇文章所能讨论的范围。在这篇文章中,我试图站在一个很高的层次上来解释它的特性,并为你提供可用来进一步学习的合适资源。Elasticsearch是非常可靠的,并且有着出色的表现(我希望你在运行范例时已经注意到了这一点)。再加之不断增长的社区支持,使得Elasticsearch在工业中的应用也在不断增加,尤其是对于需要处理实时数据或大数据的公司。
  学习完这里提供的例子之后,我强烈建议你阅读一些相关文档。文档有两个主要来源,一是Elasticsearch参考及其特性,另外还有一个指南,它更多关注的是具体实现,使用案例以及最佳实践。更多文档和源码信息请点击“阅读原文”。
  END

小技巧!前端JS实现过滤指定内容~

网站优化优采云 发表了文章 • 0 个评论 • 67 次浏览 • 2022-07-02 03:46 • 来自相关话题

  小技巧!前端JS实现过滤指定内容~
  小技巧!前端JS实现过滤指定内容~
  原创氧气 ☞☞☞
  执行上下文
  JsCoding
  一枚佛系前端开发,会一丢丢摄影,喜欢折腾,爱好美食,分享点学习经验、见闻、笔记、技巧!
  发表于
  收录于合集#前端日常问题合集11个
  戳上方“执行上下文”,选择“置顶公众号”
  关键时刻,第一时间送达!
  
  1、JS实现验证码倒计时
  /*点击获取验证码*/<br />$(".addCode").click(function(event) {<br />    var addCode = $(".addCode")<br />    verificationCode(addCode);<br />});<br />/*验证码的方法*/<br />function verificationCode(name) {<br />    var num = 20;<br />    var timer = setInterval(function() {<br />        num--;<br />        name.attr("disabled", "disabled").html(num + '秒后重试');<br />        if (num == 0) {<br />            clearInterval(timer);<br />            name.attr("disabled", false).html("重新获取");<br />        }<br />    }, 1000)<br />}<br />
  2、CSS实现文字分散对齐
  注意:只支持高版本Chrome浏览器
  text-align-last:justify;<br />text-align:justify;<br />text-justify:distribute-all-lines;<br />
  3、JS过滤指定内容
  function replaceText(words) {<br />   <br />    let text = '你是个傻逼,我才不想你这个傻逼呢。大傻逼!'<br />    for (var i = 0; i  min) {<br />        index = Math.floor((i + 1) * Math.random());<br />        item = sData[index];<br />        sData[index] = sData[i];<br />        sData[i] = item;<br />    }<br />    return sData.slice(min);<br />}<br /><br />getRandomArrayValue(groups, 4)<br /><br />// ["7", "8", "10", "2"]<br />
  前端公众号和交流群 查看全部

  小技巧!前端JS实现过滤指定内容~
  小技巧!前端JS实现过滤指定内容~
  原创氧气 ☞☞☞
  执行上下文
  JsCoding
  一枚佛系前端开发,会一丢丢摄影,喜欢折腾,爱好美食,分享点学习经验、见闻、笔记、技巧!
  发表于
  收录于合集#前端日常问题合集11个
  戳上方“执行上下文”,选择“置顶公众号”
  关键时刻,第一时间送达!
  
  1、JS实现验证码倒计时
  /*点击获取验证码*/<br />$(".addCode").click(function(event) {<br />    var addCode = $(".addCode")<br />    verificationCode(addCode);<br />});<br />/*验证码的方法*/<br />function verificationCode(name) {<br />    var num = 20;<br />    var timer = setInterval(function() {<br />        num--;<br />        name.attr("disabled", "disabled").html(num + '秒后重试');<br />        if (num == 0) {<br />            clearInterval(timer);<br />            name.attr("disabled", false).html("重新获取");<br />        }<br />    }, 1000)<br />}<br />
  2、CSS实现文字分散对齐
  注意:只支持高版本Chrome浏览器
  text-align-last:justify;<br />text-align:justify;<br />text-justify:distribute-all-lines;<br />
  3、JS过滤指定内容
  function replaceText(words) {<br />   <br />    let text = '你是个傻逼,我才不想你这个傻逼呢。大傻逼!'<br />    for (var i = 0; i  min) {<br />        index = Math.floor((i + 1) * Math.random());<br />        item = sData[index];<br />        sData[index] = sData[i];<br />        sData[i] = item;<br />    }<br />    return sData.slice(min);<br />}<br /><br />getRandomArrayValue(groups, 4)<br /><br />// ["7", "8", "10", "2"]<br />
  前端公众号和交流群

js提取指定网站内容 谈谈对vitejs预构建的理解

网站优化优采云 发表了文章 • 0 个评论 • 109 次浏览 • 2022-06-29 21:43 • 来自相关话题

  js提取指定网站内容 谈谈对vitejs预构建的理解
  vite在官网介绍中,第一条就提到的特性就是自己的本地冷启动极快。这主要是得益于它在本地服务启动的时候做了预构建。出于好奇,抽时间了解了下vite在预构建部分的主要实现思路,分享出来供大家参考。
  为啥要预构建
  简单来讲就是为了提高本地开发服务器的冷启动速度。按照vite的说法,当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。随着应用规模的增大,打包速度显著下降,本地服务器的启动速度也跟着变慢。
  为了加快本地开发服务器的启动速度,vite引入了预构建机制。在预构建工具的选择上,vite选择了esbuild。esbuild使用Go编写,比以JavaScript编写的打包器构建速度快 10-100 倍,有了预构建,再利用浏览器的esm方式按需加载业务代码,动态实时进行构建,结合缓存机制,大大提升了服务器的启动速度。
  
  预构建的流程1. 查找依赖
  如果是首次启动本地服务,那么vite会自动抓取源代码,从代码中找到需要预构建的依赖,最终对外返回类似下面的一个deps对象:
  { vue: '/path/to/your/project/node_modules/vue/dist/vue.runtime.esm-bundler.js', 'element-plus': '/path/to/your/project/node_modules/element-plus/es/index.mjs', 'vue-router': '/path/to/your/project/node_modules/vue-router/dist/vue-router.esm-bundler.js'}
  具体实现就是,调用esbuild的buildapi,以index.html作为查找入口(entryPoints),将所有的来自node_modules以及在配置文件的optimizeDeps.include选项中指定的模块找出来。
  //...省略其他代码 if (explicitEntryPatterns) { entries = await globEntries(explicitEntryPatterns, config) } else if (buildInput) { const resolvePath = (p: string) => path.resolve(config.root, p) if (typeof buildInput === 'string') { entries = [resolvePath(buildInput)] } else if (Array.isArray(buildInput)) { entries = buildInput.map(resolvePath) } else if (isObject(buildInput)) { entries = Object.values(buildInput).map(resolvePath) } else { throw new Error('invalid rollupOptions.input value.') } } else { // 重点看这里:使用html文件作为查找入口 entries = await globEntries('**/*.html', config) } //...省略其他代码build.onResolve( { // avoid matching windows volume filter: /^[\w@][^:]/ }, async ({ path: id, importer }) => { const resolved = await resolve(id, importer) if (resolved) { // 来自node_modules和在include中指定的模块 if (resolved.includes('node_modules') || include?.includes(id)) { // dependency or forced included, externalize and stop crawling<br /> if (isOptimizable(resolved)) { // 重点看这里:将符合预构建条件的依赖记录下来,depImports就是对外导出的需要预构建的依赖对象 depImports[id] = resolved } return externalUnlessEntry({ path: id }) } else if (isScannable(resolved)) { const namespace = htmlTypesRE.test(resolved) ? 'html' : undefined // linked package, keep crawling return { path: path.resolve(resolved), namespace } } else { return externalUnlessEntry({ path: id }) } } else { missing[id] = normalizePath(importer) } } )
  但是熟悉esbuild的小伙伴可能知道,esbuild默认支持的入口文件类型有js、ts、jsx、css、json、base64、dataurl、binary、file(.png等),并不包括html。vite是如何做到将index.html作为打包入口的呢?原因是vite自己实现了一个esbuild插件esbuildScanPlugin,来处理.vue和.html这种类型的文件。具体做法是读取html的内容,然后将里面的script提取到一个esm格式的js模块。
  
   // 对于html类型(.VUE/.HTML/.svelte等)的文件,提取文件里的script内容。html types: extract script contents ----------------------------------- build.onResolve({ filter: htmlTypesRE }, async ({ path, importer }) => { const resolved = await resolve(path, importer) if (!resolved) return // It is possible for the scanner to scan html types in node_modules. // If we can optimize this html type, skip it so it's handled by the // bare import resolve, and recorded as optimization dep. if (resolved.includes('node_modules') && isOptimizable(resolved)) return return { path: resolved, namespace: 'html' } })<br /> // 配合build.onResolve,对于类html文件,提取其中的script,作为一个js模块extract scripts inside HTML-like files and treat it as a js module build.onLoad( { filter: htmlTypesRE, namespace: 'html' }, async ({ path }) => { let raw = fs.readFileSync(path, 'utf-8') // Avoid matching the content of the comment raw = raw.replace(commentRE, '') const isHtml = path.endsWith('.html') const regex = isHtml ? scriptModuleRE : scriptRE regex.lastIndex = 0 // js 的内容被处理成了一个虚拟模块 let js = '' let scriptId = 0 let match: RegExpExecArray | null while ((match = regex.exec(raw))) { const [, openTag, content] = match const typeMatch = openTag.match(typeRE) const type = typeMatch && (typeMatch[1] || typeMatch[2] || typeMatch[3]) const langMatch = openTag.match(langRE) const lang = langMatch && (langMatch[1] || langMatch[2] || langMatch[3]) // skip type="application/ld+json" and other non-JS types if ( type && !( type.includes('javascript') || type.includes('ecmascript') || type === 'module' ) ) { continue } // 默认的js文件的loader是js,其他对于ts、tsx jsx有对应的同名loader let loader: Loader = 'js' if (lang === 'ts' || lang === 'tsx' || lang === 'jsx') { loader = lang } const srcMatch = openTag.match(srcRE) // 对于引入的js,将它转换为import 'path/to/some.js'的代码 if (srcMatch) { const src = srcMatch[1] || srcMatch[2] || srcMatch[3] js += `import ${JSON.stringify(src)}\n` } else if (content.trim()) { // The reason why virtual modules are needed: // 1. There can be module scripts (`` in Svelte and `` in Vue) // or local scripts (`` in Svelte and `` in Vue) // 2. There can be multiple module scripts in html // We need to handle these separately in case variable names are reused between them<br /> // append imports in TS to prevent esbuild from removing them // since they may be used in the template const contents = content + (loader.startsWith('ts') ? extractImportPaths(content) : '')<br /> // 将提取出来的script脚本,存在以xx.vue?id=1为key的script对象中script={'xx.vue?id=1': 'js contents'} const key = `${path}?id=${scriptId++}`<br /> if (contents.includes('import.meta.glob')) { scripts[key] = { // transformGlob already transforms to js loader: 'js', contents: await transformGlob( contents, path, config.root, loader, resolve, config.logger ) } } else { scripts[key] = { loader, contents } }<br /> const virtualModulePath = JSON.stringify( virtualModulePrefix + key )<br /> const contextMatch = openTag.match(contextRE) const context = contextMatch && (contextMatch[1] || contextMatch[2] || contextMatch[3])<br /> // Especially for Svelte files, exports in means module exports, // exports in means component props. To avoid having two same export name from the // star exports, we need to ignore exports in if (path.endsWith('.svelte') && context !== 'module') { js += `import ${virtualModulePath}\n` } else { // e.g. export * from 'virtual-module:xx.vue?id=1' js += `export * from ${virtualModulePath}\n` } } }<br /> // This will trigger incorrectly if `export default` is contained // anywhere in a string. Svelte and Astro files can't have // `export default` as code so we know if it's encountered it's a // false positive (e.g. contained in a string) if (!path.endsWith('.vue') || !js.includes('export default')) { js += '\nexport default {}' }<br /> return { loader: 'js', contents: js } } )
  由上文我们可知,来自node_modules中的模块依赖是需要预构建的。例如import ElementPlus from 'element-plus'。因为在浏览器环境下,是不支持这种裸模块引用的(bare import)。另一方面,如果不进行构建,浏览器面对由成百上千的子模块组成的依赖,依靠原生esm的加载机制,每个的依赖的import都将产生一次http请求。面对大量的请求,浏览器是吃不消的。因此客观上需要对裸模块引入进行打包,并处理成浏览器环境下支持的相对路径或路径的导入方式。例如:import ElementPlus from '/path/to/.vite/element-plus/es/index.mjs'。
  2. 对查找到的依赖进行构建
  在上一步,已经得到了需要预构建的依赖列表。现在需要把他们作为esbuild的entryPoints打包就行了。
  //使用esbuild打包,入口文件即为第一步中抓取到的需要预构建的依赖 import { build } from 'esbuild' // ...省略其他代码 const result = await build({ absWorkingDir: process.cwd(), // flatIdDeps即为第一步中所得到的需要预构建的依赖对象 entryPoints: Object.keys(flatIdDeps), bundle: true, format: 'esm', target: config.build.target || undefined, external: config.optimizeDeps?.exclude, logLevel: 'error', splitting: true, sourcemap: true,// outdir指定打包产物输出目录,processingCacheDir这里并不是.vite,而是存放构建产物的临时目录 outdir: processingCacheDir, ignoreAnnotations: true, metafile: true, define, plugins: [ ...plugins, esbuildDepPlugin(flatIdDeps, flatIdToExports, config, ssr) ], ...esbuildOptions })<br /> // 写入_metadata文件,并替换缓存文件。Write metadata file, delete `deps` folder and rename the new `processing` folder to `deps` in sync commitProcessingDepsCacheSync()
  vite并没有将esbuild的outdir(构建产物的输出目录)直接配置为.vite目录,而是先将构建产物存放到了一个临时目录。当构建完成后,才将原来旧的.vite(如果有的话)删除。然后再将临时目录重命名为.vite。这样做主要是为了避免在程序运行过程中发生了错误,导致缓存不可用。
   function commitProcessingDepsCacheSync() { // Rewire the file paths from the temporal processing dir to the final deps cache dir const dataPath = path.join(processingCacheDir, '_metadata.json') writeFile(dataPath, stringifyOptimizedDepsMetadata(metadata)) // Processing is done, we can now replace the depsCacheDir with processingCacheDir // 依赖处理完成后,使用依赖缓存目录替换处理中的依赖缓存目录 if (fs.existsSync(depsCacheDir)) { const rmSync = fs.rmSync ?? fs.rmdirSync // TODO: Remove after support for Node 12 is dropped rmSync(depsCacheDir, { recursive: true }) } fs.renameSync(processingCacheDir, depsCacheDir) }} 查看全部

  js提取指定网站内容 谈谈对vitejs预构建的理解
  vite在官网介绍中,第一条就提到的特性就是自己的本地冷启动极快。这主要是得益于它在本地服务启动的时候做了预构建。出于好奇,抽时间了解了下vite在预构建部分的主要实现思路,分享出来供大家参考。
  为啥要预构建
  简单来讲就是为了提高本地开发服务器的冷启动速度。按照vite的说法,当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。随着应用规模的增大,打包速度显著下降,本地服务器的启动速度也跟着变慢。
  为了加快本地开发服务器的启动速度,vite引入了预构建机制。在预构建工具的选择上,vite选择了esbuild。esbuild使用Go编写,比以JavaScript编写的打包器构建速度快 10-100 倍,有了预构建,再利用浏览器的esm方式按需加载业务代码,动态实时进行构建,结合缓存机制,大大提升了服务器的启动速度。
  
  预构建的流程1. 查找依赖
  如果是首次启动本地服务,那么vite会自动抓取源代码,从代码中找到需要预构建的依赖,最终对外返回类似下面的一个deps对象:
  { vue: '/path/to/your/project/node_modules/vue/dist/vue.runtime.esm-bundler.js', 'element-plus': '/path/to/your/project/node_modules/element-plus/es/index.mjs', 'vue-router': '/path/to/your/project/node_modules/vue-router/dist/vue-router.esm-bundler.js'}
  具体实现就是,调用esbuild的buildapi,以index.html作为查找入口(entryPoints),将所有的来自node_modules以及在配置文件的optimizeDeps.include选项中指定的模块找出来。
  //...省略其他代码 if (explicitEntryPatterns) { entries = await globEntries(explicitEntryPatterns, config) } else if (buildInput) { const resolvePath = (p: string) => path.resolve(config.root, p) if (typeof buildInput === 'string') { entries = [resolvePath(buildInput)] } else if (Array.isArray(buildInput)) { entries = buildInput.map(resolvePath) } else if (isObject(buildInput)) { entries = Object.values(buildInput).map(resolvePath) } else { throw new Error('invalid rollupOptions.input value.') } } else { // 重点看这里:使用html文件作为查找入口 entries = await globEntries('**/*.html', config) } //...省略其他代码build.onResolve( { // avoid matching windows volume filter: /^[\w@][^:]/ }, async ({ path: id, importer }) => { const resolved = await resolve(id, importer) if (resolved) { // 来自node_modules和在include中指定的模块 if (resolved.includes('node_modules') || include?.includes(id)) { // dependency or forced included, externalize and stop crawling<br /> if (isOptimizable(resolved)) { // 重点看这里:将符合预构建条件的依赖记录下来,depImports就是对外导出的需要预构建的依赖对象 depImports[id] = resolved } return externalUnlessEntry({ path: id }) } else if (isScannable(resolved)) { const namespace = htmlTypesRE.test(resolved) ? 'html' : undefined // linked package, keep crawling return { path: path.resolve(resolved), namespace } } else { return externalUnlessEntry({ path: id }) } } else { missing[id] = normalizePath(importer) } } )
  但是熟悉esbuild的小伙伴可能知道,esbuild默认支持的入口文件类型有js、ts、jsx、css、json、base64、dataurl、binary、file(.png等),并不包括html。vite是如何做到将index.html作为打包入口的呢?原因是vite自己实现了一个esbuild插件esbuildScanPlugin,来处理.vue和.html这种类型的文件。具体做法是读取html的内容,然后将里面的script提取到一个esm格式的js模块。
  
   // 对于html类型(.VUE/.HTML/.svelte等)的文件,提取文件里的script内容。html types: extract script contents ----------------------------------- build.onResolve({ filter: htmlTypesRE }, async ({ path, importer }) => { const resolved = await resolve(path, importer) if (!resolved) return // It is possible for the scanner to scan html types in node_modules. // If we can optimize this html type, skip it so it's handled by the // bare import resolve, and recorded as optimization dep. if (resolved.includes('node_modules') && isOptimizable(resolved)) return return { path: resolved, namespace: 'html' } })<br /> // 配合build.onResolve,对于类html文件,提取其中的script,作为一个js模块extract scripts inside HTML-like files and treat it as a js module build.onLoad( { filter: htmlTypesRE, namespace: 'html' }, async ({ path }) => { let raw = fs.readFileSync(path, 'utf-8') // Avoid matching the content of the comment raw = raw.replace(commentRE, '') const isHtml = path.endsWith('.html') const regex = isHtml ? scriptModuleRE : scriptRE regex.lastIndex = 0 // js 的内容被处理成了一个虚拟模块 let js = '' let scriptId = 0 let match: RegExpExecArray | null while ((match = regex.exec(raw))) { const [, openTag, content] = match const typeMatch = openTag.match(typeRE) const type = typeMatch && (typeMatch[1] || typeMatch[2] || typeMatch[3]) const langMatch = openTag.match(langRE) const lang = langMatch && (langMatch[1] || langMatch[2] || langMatch[3]) // skip type="application/ld+json" and other non-JS types if ( type && !( type.includes('javascript') || type.includes('ecmascript') || type === 'module' ) ) { continue } // 默认的js文件的loader是js,其他对于ts、tsx jsx有对应的同名loader let loader: Loader = 'js' if (lang === 'ts' || lang === 'tsx' || lang === 'jsx') { loader = lang } const srcMatch = openTag.match(srcRE) // 对于引入的js,将它转换为import 'path/to/some.js'的代码 if (srcMatch) { const src = srcMatch[1] || srcMatch[2] || srcMatch[3] js += `import ${JSON.stringify(src)}\n` } else if (content.trim()) { // The reason why virtual modules are needed: // 1. There can be module scripts (`` in Svelte and `` in Vue) // or local scripts (`` in Svelte and `` in Vue) // 2. There can be multiple module scripts in html // We need to handle these separately in case variable names are reused between them<br /> // append imports in TS to prevent esbuild from removing them // since they may be used in the template const contents = content + (loader.startsWith('ts') ? extractImportPaths(content) : '')<br /> // 将提取出来的script脚本,存在以xx.vue?id=1为key的script对象中script={'xx.vue?id=1': 'js contents'} const key = `${path}?id=${scriptId++}`<br /> if (contents.includes('import.meta.glob')) { scripts[key] = { // transformGlob already transforms to js loader: 'js', contents: await transformGlob( contents, path, config.root, loader, resolve, config.logger ) } } else { scripts[key] = { loader, contents } }<br /> const virtualModulePath = JSON.stringify( virtualModulePrefix + key )<br /> const contextMatch = openTag.match(contextRE) const context = contextMatch && (contextMatch[1] || contextMatch[2] || contextMatch[3])<br /> // Especially for Svelte files, exports in means module exports, // exports in means component props. To avoid having two same export name from the // star exports, we need to ignore exports in if (path.endsWith('.svelte') && context !== 'module') { js += `import ${virtualModulePath}\n` } else { // e.g. export * from 'virtual-module:xx.vue?id=1' js += `export * from ${virtualModulePath}\n` } } }<br /> // This will trigger incorrectly if `export default` is contained // anywhere in a string. Svelte and Astro files can't have // `export default` as code so we know if it's encountered it's a // false positive (e.g. contained in a string) if (!path.endsWith('.vue') || !js.includes('export default')) { js += '\nexport default {}' }<br /> return { loader: 'js', contents: js } } )
  由上文我们可知,来自node_modules中的模块依赖是需要预构建的。例如import ElementPlus from 'element-plus'。因为在浏览器环境下,是不支持这种裸模块引用的(bare import)。另一方面,如果不进行构建,浏览器面对由成百上千的子模块组成的依赖,依靠原生esm的加载机制,每个的依赖的import都将产生一次http请求。面对大量的请求,浏览器是吃不消的。因此客观上需要对裸模块引入进行打包,并处理成浏览器环境下支持的相对路径或路径的导入方式。例如:import ElementPlus from '/path/to/.vite/element-plus/es/index.mjs'。
  2. 对查找到的依赖进行构建
  在上一步,已经得到了需要预构建的依赖列表。现在需要把他们作为esbuild的entryPoints打包就行了。
  //使用esbuild打包,入口文件即为第一步中抓取到的需要预构建的依赖 import { build } from 'esbuild' // ...省略其他代码 const result = await build({ absWorkingDir: process.cwd(), // flatIdDeps即为第一步中所得到的需要预构建的依赖对象 entryPoints: Object.keys(flatIdDeps), bundle: true, format: 'esm', target: config.build.target || undefined, external: config.optimizeDeps?.exclude, logLevel: 'error', splitting: true, sourcemap: true,// outdir指定打包产物输出目录,processingCacheDir这里并不是.vite,而是存放构建产物的临时目录 outdir: processingCacheDir, ignoreAnnotations: true, metafile: true, define, plugins: [ ...plugins, esbuildDepPlugin(flatIdDeps, flatIdToExports, config, ssr) ], ...esbuildOptions })<br /> // 写入_metadata文件,并替换缓存文件。Write metadata file, delete `deps` folder and rename the new `processing` folder to `deps` in sync commitProcessingDepsCacheSync()
  vite并没有将esbuild的outdir(构建产物的输出目录)直接配置为.vite目录,而是先将构建产物存放到了一个临时目录。当构建完成后,才将原来旧的.vite(如果有的话)删除。然后再将临时目录重命名为.vite。这样做主要是为了避免在程序运行过程中发生了错误,导致缓存不可用。
   function commitProcessingDepsCacheSync() { // Rewire the file paths from the temporal processing dir to the final deps cache dir const dataPath = path.join(processingCacheDir, '_metadata.json') writeFile(dataPath, stringifyOptimizedDepsMetadata(metadata)) // Processing is done, we can now replace the depsCacheDir with processingCacheDir // 依赖处理完成后,使用依赖缓存目录替换处理中的依赖缓存目录 if (fs.existsSync(depsCacheDir)) { const rmSync = fs.rmSync ?? fs.rmdirSync // TODO: Remove after support for Node 12 is dropped rmSync(depsCacheDir, { recursive: true }) } fs.renameSync(processingCacheDir, depsCacheDir) }}

js提取指定网站内容 JavaScript SEO 终极指南(Google SEOer必看)

网站优化优采云 发表了文章 • 0 个评论 • 132 次浏览 • 2022-06-29 06:10 • 来自相关话题

  js提取指定网站内容 JavaScript SEO 终极指南(Google SEOer必看)
  5.分类筛选器
  所以,如果这些内容在JavaScript 上没有处理好的话,很容易造成索引及排名上遇到困难。
  那如何检查网页上哪些内容是JavaScript 所产生的呢
  一、通过使用Chrome 插件:
  这边介绍的工具叫做『Quick Javascript Switcher』,这个插件可以直接开关网页的JavaScript 功能,只要你关掉JavaScript 后,发现哪个部分的内容不见了,那很大程度就是那个内容是JavaScript 所产生。
  从下图可以看到,当我们用插件关掉JavaScript 功能后,Pressplay 的主要内容消失不见了,那就代表说其中主要内容由JavaScript 所产生。
  二、从开发者工具关闭
  首先点击鼠标右键找到『检查』,你会进入开发者介面。
  接着使用快捷键『Control + Shift + p』 (Windows) 或是『Command + Option + p』 (Mac)。
  接着在光标处中输入JavaScript,就会看到一个『Disable JavaScript』选项,点击即可关闭JavaScript,同理要再打开只需使用相同方法再点击一次便可打开JavaScript 功能。
  为什么网页源代码没有JavaScript 产生的内容!?
  一般来说,我们在检查网页中的meta 标签、H 标签等内容时,最常做的就是从网页源代码中去查看,也就是『右键> 检查网页源代码』所呈现的内容。
  而这个文件就是HTML 文件,但这份HTML 文件仅仅代表浏览器在解析页面时的最初讯息,而JavaScript 所产生的内容并不在一开始的HTML 文件上。
  所以,检查网页源代码无法知道JavaScript 更新后的动态内容。
  此时就要介绍一下HTML 加工后的DOM 了,这边为了不复杂化,简单叙述一下,当你『右键> 检查』出来的东西便是加工过的DOM(如下图)。DOM 里面会随着你与网站的互动,将JavaScript 所产生的内容加上去。
  那如何区分HTML 源代码还是加工后的DOM 呢?
  PS: 如果Google 爬取页面时无法完整呈现JavaScript 产生的页面,它至少可以索引为加载过的HTML 原始码。
  在确认并且知道哪些内容属于JavaScript 所产生的之后,再就是理解Google 怎么爬取JavaScript,并且优化你的内容让网页排名上升。
  二、Google 怎么爬取JS 网站
  对于搜索引擎而言,JavaScript 一直是Google 努力在改善爬虫技术,让搜索引擎索引并排名的目标之一。虽然JavaScript 为访客带来更良好的使用体验,但是对于搜索引擎而言却不是一件容易的事情,请记得:
  根据onely 网站调查指出,许多大品牌网页上JavaScript 之内容未被索引的情况:
  你可以想像,Yoox 在国外是知名电商网站,每个月可以有高达1400 万的流量,但是网站由JavaScript 产生的内容竟然由高达92% 是Google 不会索引到的,由此可知这样对SEO 的影响可以有多大,损失又可以有多多。
  但同样的,也有把JavaScript 所产生的内容处理的很好的网站, 以及 的网站分别让JavaScript 所产生的内容,被100% 及99% 的索引了,所以,只要方法得当,我们也能让JavaScript 与SEO 兼顾。
  Google 爬取页面的过程
  在早期搜索引擎只需要下载HTML 档便可完整了解网页内容,但由于JavaScript 技术的崛起及普及,搜索引擎甚至需要像浏览器一样,以便他们以访客的角度查看网页内容。
  而Google 处理渲染的系统,被称为Web Rendering Service (WRS),中文可以翻译成网页渲染器,后面以WRS 代称,而Google 也给出了一张简化的图作为说明。
  简单说明Google 爬取步骤,传统爬取HTML 档页面时,每项元素都很好爬取,整个索引并排名页面的过程也迅速:
  1.Google bot 下载HTML 档
  2.Google bot 从源代码中提取url 网址,并快速访问这些url
  3.Google bot 下载CSS 档案
  4.Google bot 将下载下来的资源送到Google 的Indexer
  5.Google 的Indexer 检索页面
  但如果是今天爬取JavaScript 所产生的网站内容的话,Google 会怎么爬取呢:
  1.Google bot 下载HTML 档
  2.Google bot 在源代码中找不到链接,因为JavaScript 未被执行
  3.Google bot 下载CSS 及JavaScript 档案
  4.Google bot 使用WRS(渲染器,Indexer 的一部分)解析、编译并执行JavaScript
  5.WRS 从外部API、资料库获取资料(data)
  6.Indexer 可以索引内容
  7.Google 发现新的链接,并将其加入爬取排队队伍之中(Googlebot's crawling queue)。至此,执行一般Google bot 爬取HTML 页面的第二步。
  可以发现,为了渲染出页面,Google 多了许多步骤。再来讲一下渲染过程中,Crawler、Processing、Renderer 及Index 之重要节点。
  三、Google 爬取JavaScript 过程中的重要节点
  Crawler(爬虫)
  首先,crawler 会先向网站服务器发送一段请求(request),网站服务器会返回内容及其标头(header),然后crawler 将它储存起来。
  而由于mobile-first indexing的关系,发送请求的可能大多都是来自手机版的爬虫(mobile user-agent),从Google Search Console上可以检查到,你可以透过网址审查或是涵盖范围来知道现在是电脑版索引还是手机版优先索引的状态。
  然后有些网站会使用user-agent detection,侦测访客来到自己网站时,是用手机还是桌机、浏览器是什么、浏览器版本的不同资讯,再根据这些资讯给访客相对应的资讯,例如今天侦测到访客是用手机版本的chrome,便呈现手机版的页面给访客看。
  需要注意的是,有些网站遇到爬虫时可能会设定禁止该爬虫爬取页面,或是禁止特定地区ip 的访客查看页面,这时候就要小心如果网页没设定好的话,很有可能爬虫是看不到你的内容的喔。
  记得从几个方面测试看看Google 爬虫能否顺利看到你的页面:Google Search Console 的网址检查器、移动友好测试工具以及富媒体结果测试工具。
  补充:从爬取过程那张图可以看到,Google 将爬取后产生的页面称之为HTML,但实际上,为了建构页面内容,Google 其实爬取并储存了相关所需的资源,像是CSS 文档、JS 文档、API 端口、XHR requests等相关资源。
  Processing(处理)
  Processing 的过程中其实是非常复杂且处理很多事的,这边重点讲述Google 处理JavaScript 的过程。
  (一)遵循限制性最高的要求
  什么是限制性最高的要求,就是假设今天Google 渲染(render)出页面后,原本meta robots 的信息是index 被加入了noindex,那么Google 将不会索引其页面,甚至其它尚未被渲染的页面,因为JS 产生noindex 这类的语法,则可能导致页面无法被渲染。
  (二)处理资源及链接
  Google 并不像访客那样浏览页面,Processing 的过程中有个很重要的工作便是检查页面上的链接以及建构该页面所需的文档。
  这些链接被记录,加到等待爬取的排队序列中(crawl queue),反覆执行找链接、链接排队、爬取链接,便是Google 本身爬取整个网路世界的方式。
  Google 透过属性,将建构页面所需的资源,像是JS、CSS 文档被记录。但是页面对页面的链接需要以特定的形式所呈现,才能被Google 所抓取,那就是以链接”>的形式。
  
  能被爬取的連結a>
  不能被爬取的連結span>
  不能被爬取的連結a>
  能被爬取的連結a>
  如果你的链接是JavaScript 所产生的话,那必须等到页面被渲染后,爬虫才能爬到。但有个风险就是,不一定页面上的内容全数都能被成功渲染,有可能因为检索预算不足的情况下渲染不到你的链接,所以务必留意链接的部分。
  (三)删除重复内容
  Google 倾向将重复页面删除,或者是降低重复页面的爬取优先级别。许多JavaScript 所产生的网页,都会有个app shell models,可以想像他是最小化的HTML、CSS 及JS 所组成,用户可以在不同需求下再次载入所需要的内容。
  但这有一个问题就是,app shell models 只有最简单少量的内容及源代码,所以很有可能被Google 误判为重复性内容,也造成其页面能够被渲染的优先级下降,正确的内容无法被索引,以及错误的页面被排名。
  (四)缓存及其它
  Google 下载页面HTML、CSS、JS 文档并渲染后,就会将其缓存。并且还有其它许多事情是Google 会同时处理的,并不止于这些,但处理页面的部分重点就在上述几项。
  Render queue (渲染序列)
  接下来许多页面即将被渲染, 所以在渲染排队中,根据Google 早期的说法,由于检索预算的优化,渲染页面并检索会是比较后期的事,俗称第二波索引( two waves of indexing ),但其实在近期onely 的Bartosz Goralewicz 与John 及Martin 讲述到,第二波索引的影响其实越来越小,Google 在等待渲染的中位数时间也只有5 秒钟,可见Google 在渲染并索引这一块下了相当大的功夫,未来渲染也将与检索能够同步进行‍。
  Renderer(渲染器)
  还记得前面说的食谱与料理吗?页面在渲染前的DOM 跟渲染后的DOM 就像料理的食谱,以及做好的烤鸡一样,简单讲DOM 就是像图中那树状图所呈现。
  料理前的食谱是不会改变的,所以渲染前的页面源代码一样不会因触发JavaScript 而改变,所以可以想像Renderer 就是一个主厨,料理食谱并且产生一道料理(JavaScript 渲染出来的页面),Renderer 为的就是去渲染出JavaScript 相关内容。
  要知道光是可以爬取整个网路世界成千上亿的资料便是不容易,还要将其内容渲染出来耗费资源非同小可,根据onely 指出,为了让JavaScript 内容被爬取、渲染并且索引,耗费的资源是一般HTML 页面的20 倍,一定要格外小心。让我们看看渲染器中有哪些重要的东西吧。
  (1)快取资源(Cache Resource)
  Google 相当重度依赖快取,它会快取各种文档,文档快取、页面快取、API requests 等,在被送到渲染器前就会先快取起来。因为不太可能每准备渲染一页,Google 就下载一次资源,所以优先快取好的文档资源就能快速渲染页面。
  但这也带来几个问题,有可能Google 会快取到旧的档案、旧版本的资源,导致在渲染页面时出现错误。如果有这种状况出现记得做好版本控制或是内容指纹,让Google 可以知道你更新了新的内容。
  (2)没有特定逾时时间(No Fixed Timeout)
  很多网上谣传渲染器只会用5 秒渲染你的页面,但其实并不然,Google 渲染时可能会加载原有快取的档案,会有5 秒的这一说法,主要是因为网址审查工具相关工具,检测页面时需要获取资源所以需要设立合理的逾时时间。
  为了确保内容完整呈现,Google 没有特地设定逾时时间,但为了爬虫爬取及访客体验,更快的速度一定是更好的。
  (3)渲染后,Google 看到了什么?
  这边要提到一个很重要的点是,Google 并不会主动与网页上的内容做互动,所以有些JavaScript 的特效,需要访客点击或触发的特效,是不会被Google 所触发,不会点击更不会滚动页面。
  所以早期你们一定有听过一个说法,不要使用瀑布流网页的原因就是如此,因为Google 不会卷动你页面的情况下,就无法触发JavaScript 所产生的内容,但Google 也不笨喔,为了克服瀑布流,他们直接把机器人设定成一台超长版手机,这样可以直接渲染出指定长度的内容。
  可是一般需要JavaScript 触发的内容无法被Google 渲染出来了喔,所以一定要特别注意,链接也不要出现JavaScript 所产生之链接。
  四、如何打造JavaScript 友善的网站
  前面我们说到JavaScript 现在越来越重要,也是越来越多网站使用的技术,所以与其完全避开使用JavaScript,不如打造一个既能满足开发者需求,又能争取排名的JavaScript 网站,让来看看有哪些重要因素吧。
  1.可被爬取(Crawlability):确保你的网站能保持良好的结构被爬取,并且爬虫也能找到有价值的内容。
  2.可被渲染(Renderability):确保页面上的内容可以被渲染。
  3.爬取预算(Crawl budget):Google 花了多少资源及时间渲染你的页面
  你的JavaScript 内容对搜索引擎足够友善吗?
  首先检查。你要知道你的网页在Google 眼中长的如何,那到底有哪些常见检查方法,这些方法正确吗?
  1.透过网址审查工具
  Google Search Console 的网站审查工具可以呈现渲染后的页面,其它官方的工具包含AMP 测试工具、富媒体搜索结果测试等官方检测工具,皆能呈现出渲染后的样貌,这边以移动友好测试工具为例。
  可以看到屏幕截图的画面,显示出Google 渲染出的画面,可以试着去看屏幕截图,重要内容是否能够被渲染出来。
  渲染后的屏幕画面
  另一方,你可以从检查工具的源代码中查看内容是否有被渲染出来,直接搜索内容、H 标签等方式确认。
  记得从渲染后的HTML(DOM – the rendered code)检查:
  2.site 指令+关键字检查
  site 指令一般而言,大多用来检查页面在Google 之收录状况,那如果说你直接『site:网址』后发现页面有被Google 收录,你就能用这个方法检查,因为Google 其实会根据关键字修改搜索结果页上的Description,所以当你输入一段内文时,Google 其实很有可能根据你这一段内文呈现在Description 上给你看。
  以pressplay 页面为例,pressplay 上的课程简介其实就是用JavaScript 去产生的,下图中可以看到,当我们将JavaScript 功能关闭时,就会发现内容只剩下下面那一段,那么要确认Google 是否有索引到主要内容便可用『site 指令+关键字』做检查。
  只有上面红框文字非JavaScript 产生。
  而在连老师『每月给你SEO最新趋势』这堂课中会发现,只要将JavaScript 功能关掉,主要内容便只剩下其中红框这一段,再来,复制一段JavaScript 产生内容的文字『每年服务客户横跨12大产业,我们了解你的产业问题,资深SEO专家团队陪你洞悉新·SEO』+ site:网址试试看。
  有没有发现,其实JavaScript 产生的内容Google 是有渲染出来并且索引到的,但如果要更准确的检查,建议还是要从官方的网址测试工具查看。
  注:网址审查工具:
  Google Search Console 网址审查工具#%E7%B6%B2%E5%9D%80%E5%AF%A9%E6%9F%A5
  结构化测试工具
  富媒体搜索结果测试工具
  AMP 测试工具
  移动友好检测工具
  Google 无法索引我的网页怎么办
  刚刚前面有提到,透过网址审查工具首先检查Google 渲染页面的状态为何,如果渲染未出现主要内容,那么就可能导致内容无法被索引,你需要透过网址审查工具中的更多信息,查看是否有资源遭到阻挡。
  更多信息中会告诉你哪些资源遭到封锁
  所以,先确保内容是否能被正确渲染后,再确保能否被索引,接着才能优化内容竞争排名。
  Google 未能索引你网页的原因:
  了解Google是否能渲染你的内容,是否能正确索引,然后再争取排名,一步步找出问题并解决它。
  五、渲染方式的不同:向Google 展示JavaScript 内容的不同方式
  你以为你的页面对Google 来说只是渲染出来,然后查看内容、收录并且排名吗?其实没那么简单,网页渲染的呈现方式还能分为客户端渲染(Client Side Rendering)、服务器端渲染(Server Side Rendering)、混合式渲染等方式。
  
  SSR(服务器端渲染),通常对于Google bot 以及访客而言,能够接受到完整的HTML 档案,内容也已经呈现好了。
  CSR(客户端渲染),近几年来越来越流行的渲染方式,对于Google bot 及访客而言,最初拿到的页面几乎是空白的HTML 档案,随着访客的操作,JavaScript 非同步的产生并下载内容。用料理与食谱来比喻,Google bot 及访客都只拿到了一份食谱,后面呈现端看访客如何烘培蛋糕(操作网站)。
  但是,Google bot 并不像访客一样,会有许多花里胡哨的操作,Google bot 不会滚动、不会点击更不会跟网站进行互动,所以如果你是全CSR(客户端渲染)的页面一定要注意,解决方法如下:
  ①服务器端渲染(SSR)
  敞偌你的页面因为JavaScript 渲染问题导致页面无法被索引,那强烈建议将重要页面或是网站改成服务器端渲染。
  ②动态渲染(Dynamic Rendering )
  有时候当然不可能说全改成SSR ,于是动态渲染就变成当今蛮重要的一种渲染方式,能同时做到CSR 想呈现的效果,又能同时达到SEO 排名。
  从下图可以看到,网页使用了全JavaScript 所产生的内容,但是提供给Google bot 的是另一静态HTML 页面,很好的解决了Google 爬虫无法查看渲染页面的问题。
  以下三种服务可以很好的帮助你实现动态渲染功能:
  Prerender.io
  Puppeteer
  Rendertron #0
  Google 官方文件也提供了转译原理、说明及方式,推荐大家看看。而下图是各种渲染JavaScript 的方法,其实大部分对于Google 来说都是渲染的出来的,比较难的还是在CSR(客户端渲染)的部分,所以如果你是CSR 建议导入动态渲染喔。
  六、如何建构一个友善SEO 的JavaScript 网站
  其实这个小节的内容有部分你可能过去就知道了,但因为JavaScript 的关系仍有部分不同。
  允许Google 爬取
  如果连网页都不能爬取、渲染的JavaScript 资源都无法读取的话,就不用说要排名啰,记得Robots.txt里不要禁止渲染相关资源,在Robots.txt中加入以下指令:
  User-Agent: Googlebot
  Allow: .js
  Allow: .css
  On-page 优化
  基本上on-page 上的重要元素应该都要能够被呈现出来,记得透过网址审查工具仔细检查是否都有出现:
  JavaScript 网站最常出现的一个状况是重复Title/Description 被重复使用,记得可以从Google Search Console 中的涵盖范围查看,又或者透过Screaming Frog 等工具确认。
  网址的点击
  前面虽然都有提到,但这边还是正式说明一下,在2018 年的Google I/O 大会上便说到,因为Googlebot 并不会去点击、滚动或是与网页做互动,所以如果你的链接是以onclick 的方式呈现的话,将不会被Googlebot 所爬取。
  对Google 而言,好链接与坏链接
  同样的,在导航上、分页上、内容上一样切记要使用 的方式去呈现链接,才能确保Google 会发现并爬取你的链接。
  网址的更新
  对于部分网页采用SPA(Single Page Application)方式所呈现的网页,在更新网页时,必须使用History API,对于较早期的开发者而言,在更新网页Url 时采用的是片段(fragement)的方式,那网址就会变成我们常见的锚点,如下:
  Our products
  但以『#』这种形式的连结对于Google 来说并不会抓取喔!虽然早期开发出一种连结形式,将『#』取代成『#!』,但这种方式已经过时了,网址也会变得相当丑。
  但是透过History API 的方式就能让网页资讯变动时,链接才会变换成Google 可爬取的形式,完整介绍可参考Google 官方文件。
  错误页面
  因为JavaScript 框架是客户端而非伺服务器端,所以像是当SPA 页面产生错误时,并没有办法传递出404 状态码到服务器中,此时请采取以下其中一种方式解决:
  l使用JavaScript 转移到你原本就设定好404 状态码及页面不存在讯息之页面
  l将错误页面加上noindex 标签,并在页面上呈现『404 页面错误』信息,这样子页面就能被视作软404(soft 404)的状态。
  Sitemap
  我们可能因为使用JavaScript 产生了网站的许多内容,并没有办法说一次到位,解决所有JavaScript 产生的SEO 问题,此时Sitemap.xml 有着重要的角色,就是告知Google 网站重要的页面有哪些,对于你提交的页面,Google 可能会优先爬取。
  但同时,你也必须确保Sitemap 上的所有页面链接没有以下问题:
  重复内容
  被canonical 指到别的页面
  404 错误页面
  301 转址到其它页面
  空白页面
  等等…
  这样Sitemap 才能真正的发挥他的作用,让Google 知道你重要的页面。
  总结
  JavaScript 所产生的内容,已经不像过往几年Google 爬虫完全无法理解,随着开发技术的进步JavaScript 也成为网页开发的重要元素,所以不要急着排斥它。
  记得首先,让Google 能够渲染出你的页面;其次,确认Google 有顺利索引你的页面;接着,按着你一般优化SEO 的方式,排除重复内容、优化内容,加强关键字排名。
  这看似简单的几个步骤就花了很大一个篇幅在说明了,所以一起努力建立一个友善SEO 的JavaScript 网站吧!
  参考资料:
  l了解JavaScript 搜寻引擎最佳化(SEO) 基础知识
  l修正会影响搜寻体验的JavaScript 问题
  l导入动态转译
  lRendering on the Web
  lJavaScript SEO: What You Need to Know
  lThe Ultimate Guide to JavaScript SEO (2020 Edition)
  lJavaScript and SEO: The Difference Between Crawling and Indexing
  lMaking JavaScript and Google Search work together
  lRendering SEO manifesto – why JavaScript SEO is not enough
  lJavaScript vs. Crawl Budget: Ready Player One
  lEverything You Know About JavaScript Indexing is Wrong
  lStatic vs. Server Rendering
  lDeliver search-friendly JavaScript-powered websites (Google I/O '18)
  lJavaScript SEO – How Does Google Crawl JavaScript 查看全部

  js提取指定网站内容 JavaScript SEO 终极指南(Google SEOer必看)
  5.分类筛选器
  所以,如果这些内容在JavaScript 上没有处理好的话,很容易造成索引及排名上遇到困难。
  那如何检查网页上哪些内容是JavaScript 所产生的呢
  一、通过使用Chrome 插件:
  这边介绍的工具叫做『Quick Javascript Switcher』,这个插件可以直接开关网页的JavaScript 功能,只要你关掉JavaScript 后,发现哪个部分的内容不见了,那很大程度就是那个内容是JavaScript 所产生。
  从下图可以看到,当我们用插件关掉JavaScript 功能后,Pressplay 的主要内容消失不见了,那就代表说其中主要内容由JavaScript 所产生。
  二、从开发者工具关闭
  首先点击鼠标右键找到『检查』,你会进入开发者介面。
  接着使用快捷键『Control + Shift + p』 (Windows) 或是『Command + Option + p』 (Mac)。
  接着在光标处中输入JavaScript,就会看到一个『Disable JavaScript』选项,点击即可关闭JavaScript,同理要再打开只需使用相同方法再点击一次便可打开JavaScript 功能。
  为什么网页源代码没有JavaScript 产生的内容!?
  一般来说,我们在检查网页中的meta 标签、H 标签等内容时,最常做的就是从网页源代码中去查看,也就是『右键> 检查网页源代码』所呈现的内容。
  而这个文件就是HTML 文件,但这份HTML 文件仅仅代表浏览器在解析页面时的最初讯息,而JavaScript 所产生的内容并不在一开始的HTML 文件上。
  所以,检查网页源代码无法知道JavaScript 更新后的动态内容。
  此时就要介绍一下HTML 加工后的DOM 了,这边为了不复杂化,简单叙述一下,当你『右键> 检查』出来的东西便是加工过的DOM(如下图)。DOM 里面会随着你与网站的互动,将JavaScript 所产生的内容加上去。
  那如何区分HTML 源代码还是加工后的DOM 呢?
  PS: 如果Google 爬取页面时无法完整呈现JavaScript 产生的页面,它至少可以索引为加载过的HTML 原始码。
  在确认并且知道哪些内容属于JavaScript 所产生的之后,再就是理解Google 怎么爬取JavaScript,并且优化你的内容让网页排名上升。
  二、Google 怎么爬取JS 网站
  对于搜索引擎而言,JavaScript 一直是Google 努力在改善爬虫技术,让搜索引擎索引并排名的目标之一。虽然JavaScript 为访客带来更良好的使用体验,但是对于搜索引擎而言却不是一件容易的事情,请记得:
  根据onely 网站调查指出,许多大品牌网页上JavaScript 之内容未被索引的情况:
  你可以想像,Yoox 在国外是知名电商网站,每个月可以有高达1400 万的流量,但是网站由JavaScript 产生的内容竟然由高达92% 是Google 不会索引到的,由此可知这样对SEO 的影响可以有多大,损失又可以有多多。
  但同样的,也有把JavaScript 所产生的内容处理的很好的网站, 以及 的网站分别让JavaScript 所产生的内容,被100% 及99% 的索引了,所以,只要方法得当,我们也能让JavaScript 与SEO 兼顾。
  Google 爬取页面的过程
  在早期搜索引擎只需要下载HTML 档便可完整了解网页内容,但由于JavaScript 技术的崛起及普及,搜索引擎甚至需要像浏览器一样,以便他们以访客的角度查看网页内容。
  而Google 处理渲染的系统,被称为Web Rendering Service (WRS),中文可以翻译成网页渲染器,后面以WRS 代称,而Google 也给出了一张简化的图作为说明。
  简单说明Google 爬取步骤,传统爬取HTML 档页面时,每项元素都很好爬取,整个索引并排名页面的过程也迅速:
  1.Google bot 下载HTML 档
  2.Google bot 从源代码中提取url 网址,并快速访问这些url
  3.Google bot 下载CSS 档案
  4.Google bot 将下载下来的资源送到Google 的Indexer
  5.Google 的Indexer 检索页面
  但如果是今天爬取JavaScript 所产生的网站内容的话,Google 会怎么爬取呢:
  1.Google bot 下载HTML 档
  2.Google bot 在源代码中找不到链接,因为JavaScript 未被执行
  3.Google bot 下载CSS 及JavaScript 档案
  4.Google bot 使用WRS(渲染器,Indexer 的一部分)解析、编译并执行JavaScript
  5.WRS 从外部API、资料库获取资料(data)
  6.Indexer 可以索引内容
  7.Google 发现新的链接,并将其加入爬取排队队伍之中(Googlebot's crawling queue)。至此,执行一般Google bot 爬取HTML 页面的第二步。
  可以发现,为了渲染出页面,Google 多了许多步骤。再来讲一下渲染过程中,Crawler、Processing、Renderer 及Index 之重要节点。
  三、Google 爬取JavaScript 过程中的重要节点
  Crawler(爬虫)
  首先,crawler 会先向网站服务器发送一段请求(request),网站服务器会返回内容及其标头(header),然后crawler 将它储存起来。
  而由于mobile-first indexing的关系,发送请求的可能大多都是来自手机版的爬虫(mobile user-agent),从Google Search Console上可以检查到,你可以透过网址审查或是涵盖范围来知道现在是电脑版索引还是手机版优先索引的状态。
  然后有些网站会使用user-agent detection,侦测访客来到自己网站时,是用手机还是桌机、浏览器是什么、浏览器版本的不同资讯,再根据这些资讯给访客相对应的资讯,例如今天侦测到访客是用手机版本的chrome,便呈现手机版的页面给访客看。
  需要注意的是,有些网站遇到爬虫时可能会设定禁止该爬虫爬取页面,或是禁止特定地区ip 的访客查看页面,这时候就要小心如果网页没设定好的话,很有可能爬虫是看不到你的内容的喔。
  记得从几个方面测试看看Google 爬虫能否顺利看到你的页面:Google Search Console 的网址检查器、移动友好测试工具以及富媒体结果测试工具。
  补充:从爬取过程那张图可以看到,Google 将爬取后产生的页面称之为HTML,但实际上,为了建构页面内容,Google 其实爬取并储存了相关所需的资源,像是CSS 文档、JS 文档、API 端口、XHR requests等相关资源。
  Processing(处理)
  Processing 的过程中其实是非常复杂且处理很多事的,这边重点讲述Google 处理JavaScript 的过程。
  (一)遵循限制性最高的要求
  什么是限制性最高的要求,就是假设今天Google 渲染(render)出页面后,原本meta robots 的信息是index 被加入了noindex,那么Google 将不会索引其页面,甚至其它尚未被渲染的页面,因为JS 产生noindex 这类的语法,则可能导致页面无法被渲染。
  (二)处理资源及链接
  Google 并不像访客那样浏览页面,Processing 的过程中有个很重要的工作便是检查页面上的链接以及建构该页面所需的文档。
  这些链接被记录,加到等待爬取的排队序列中(crawl queue),反覆执行找链接、链接排队、爬取链接,便是Google 本身爬取整个网路世界的方式。
  Google 透过属性,将建构页面所需的资源,像是JS、CSS 文档被记录。但是页面对页面的链接需要以特定的形式所呈现,才能被Google 所抓取,那就是以链接”>的形式。
  
  能被爬取的連結a>
  不能被爬取的連結span>
  不能被爬取的連結a>
  能被爬取的連結a>
  如果你的链接是JavaScript 所产生的话,那必须等到页面被渲染后,爬虫才能爬到。但有个风险就是,不一定页面上的内容全数都能被成功渲染,有可能因为检索预算不足的情况下渲染不到你的链接,所以务必留意链接的部分。
  (三)删除重复内容
  Google 倾向将重复页面删除,或者是降低重复页面的爬取优先级别。许多JavaScript 所产生的网页,都会有个app shell models,可以想像他是最小化的HTML、CSS 及JS 所组成,用户可以在不同需求下再次载入所需要的内容。
  但这有一个问题就是,app shell models 只有最简单少量的内容及源代码,所以很有可能被Google 误判为重复性内容,也造成其页面能够被渲染的优先级下降,正确的内容无法被索引,以及错误的页面被排名。
  (四)缓存及其它
  Google 下载页面HTML、CSS、JS 文档并渲染后,就会将其缓存。并且还有其它许多事情是Google 会同时处理的,并不止于这些,但处理页面的部分重点就在上述几项。
  Render queue (渲染序列)
  接下来许多页面即将被渲染, 所以在渲染排队中,根据Google 早期的说法,由于检索预算的优化,渲染页面并检索会是比较后期的事,俗称第二波索引( two waves of indexing ),但其实在近期onely 的Bartosz Goralewicz 与John 及Martin 讲述到,第二波索引的影响其实越来越小,Google 在等待渲染的中位数时间也只有5 秒钟,可见Google 在渲染并索引这一块下了相当大的功夫,未来渲染也将与检索能够同步进行‍。
  Renderer(渲染器)
  还记得前面说的食谱与料理吗?页面在渲染前的DOM 跟渲染后的DOM 就像料理的食谱,以及做好的烤鸡一样,简单讲DOM 就是像图中那树状图所呈现。
  料理前的食谱是不会改变的,所以渲染前的页面源代码一样不会因触发JavaScript 而改变,所以可以想像Renderer 就是一个主厨,料理食谱并且产生一道料理(JavaScript 渲染出来的页面),Renderer 为的就是去渲染出JavaScript 相关内容。
  要知道光是可以爬取整个网路世界成千上亿的资料便是不容易,还要将其内容渲染出来耗费资源非同小可,根据onely 指出,为了让JavaScript 内容被爬取、渲染并且索引,耗费的资源是一般HTML 页面的20 倍,一定要格外小心。让我们看看渲染器中有哪些重要的东西吧。
  (1)快取资源(Cache Resource)
  Google 相当重度依赖快取,它会快取各种文档,文档快取、页面快取、API requests 等,在被送到渲染器前就会先快取起来。因为不太可能每准备渲染一页,Google 就下载一次资源,所以优先快取好的文档资源就能快速渲染页面。
  但这也带来几个问题,有可能Google 会快取到旧的档案、旧版本的资源,导致在渲染页面时出现错误。如果有这种状况出现记得做好版本控制或是内容指纹,让Google 可以知道你更新了新的内容。
  (2)没有特定逾时时间(No Fixed Timeout)
  很多网上谣传渲染器只会用5 秒渲染你的页面,但其实并不然,Google 渲染时可能会加载原有快取的档案,会有5 秒的这一说法,主要是因为网址审查工具相关工具,检测页面时需要获取资源所以需要设立合理的逾时时间。
  为了确保内容完整呈现,Google 没有特地设定逾时时间,但为了爬虫爬取及访客体验,更快的速度一定是更好的。
  (3)渲染后,Google 看到了什么?
  这边要提到一个很重要的点是,Google 并不会主动与网页上的内容做互动,所以有些JavaScript 的特效,需要访客点击或触发的特效,是不会被Google 所触发,不会点击更不会滚动页面。
  所以早期你们一定有听过一个说法,不要使用瀑布流网页的原因就是如此,因为Google 不会卷动你页面的情况下,就无法触发JavaScript 所产生的内容,但Google 也不笨喔,为了克服瀑布流,他们直接把机器人设定成一台超长版手机,这样可以直接渲染出指定长度的内容。
  可是一般需要JavaScript 触发的内容无法被Google 渲染出来了喔,所以一定要特别注意,链接也不要出现JavaScript 所产生之链接。
  四、如何打造JavaScript 友善的网站
  前面我们说到JavaScript 现在越来越重要,也是越来越多网站使用的技术,所以与其完全避开使用JavaScript,不如打造一个既能满足开发者需求,又能争取排名的JavaScript 网站,让来看看有哪些重要因素吧。
  1.可被爬取(Crawlability):确保你的网站能保持良好的结构被爬取,并且爬虫也能找到有价值的内容。
  2.可被渲染(Renderability):确保页面上的内容可以被渲染。
  3.爬取预算(Crawl budget):Google 花了多少资源及时间渲染你的页面
  你的JavaScript 内容对搜索引擎足够友善吗?
  首先检查。你要知道你的网页在Google 眼中长的如何,那到底有哪些常见检查方法,这些方法正确吗?
  1.透过网址审查工具
  Google Search Console 的网站审查工具可以呈现渲染后的页面,其它官方的工具包含AMP 测试工具、富媒体搜索结果测试等官方检测工具,皆能呈现出渲染后的样貌,这边以移动友好测试工具为例。
  可以看到屏幕截图的画面,显示出Google 渲染出的画面,可以试着去看屏幕截图,重要内容是否能够被渲染出来。
  渲染后的屏幕画面
  另一方,你可以从检查工具的源代码中查看内容是否有被渲染出来,直接搜索内容、H 标签等方式确认。
  记得从渲染后的HTML(DOM – the rendered code)检查:
  2.site 指令+关键字检查
  site 指令一般而言,大多用来检查页面在Google 之收录状况,那如果说你直接『site:网址』后发现页面有被Google 收录,你就能用这个方法检查,因为Google 其实会根据关键字修改搜索结果页上的Description,所以当你输入一段内文时,Google 其实很有可能根据你这一段内文呈现在Description 上给你看。
  以pressplay 页面为例,pressplay 上的课程简介其实就是用JavaScript 去产生的,下图中可以看到,当我们将JavaScript 功能关闭时,就会发现内容只剩下下面那一段,那么要确认Google 是否有索引到主要内容便可用『site 指令+关键字』做检查。
  只有上面红框文字非JavaScript 产生。
  而在连老师『每月给你SEO最新趋势』这堂课中会发现,只要将JavaScript 功能关掉,主要内容便只剩下其中红框这一段,再来,复制一段JavaScript 产生内容的文字『每年服务客户横跨12大产业,我们了解你的产业问题,资深SEO专家团队陪你洞悉新·SEO』+ site:网址试试看。
  有没有发现,其实JavaScript 产生的内容Google 是有渲染出来并且索引到的,但如果要更准确的检查,建议还是要从官方的网址测试工具查看。
  注:网址审查工具:
  Google Search Console 网址审查工具#%E7%B6%B2%E5%9D%80%E5%AF%A9%E6%9F%A5
  结构化测试工具
  富媒体搜索结果测试工具
  AMP 测试工具
  移动友好检测工具
  Google 无法索引我的网页怎么办
  刚刚前面有提到,透过网址审查工具首先检查Google 渲染页面的状态为何,如果渲染未出现主要内容,那么就可能导致内容无法被索引,你需要透过网址审查工具中的更多信息,查看是否有资源遭到阻挡。
  更多信息中会告诉你哪些资源遭到封锁
  所以,先确保内容是否能被正确渲染后,再确保能否被索引,接着才能优化内容竞争排名。
  Google 未能索引你网页的原因:
  了解Google是否能渲染你的内容,是否能正确索引,然后再争取排名,一步步找出问题并解决它。
  五、渲染方式的不同:向Google 展示JavaScript 内容的不同方式
  你以为你的页面对Google 来说只是渲染出来,然后查看内容、收录并且排名吗?其实没那么简单,网页渲染的呈现方式还能分为客户端渲染(Client Side Rendering)、服务器端渲染(Server Side Rendering)、混合式渲染等方式。
  
  SSR(服务器端渲染),通常对于Google bot 以及访客而言,能够接受到完整的HTML 档案,内容也已经呈现好了。
  CSR(客户端渲染),近几年来越来越流行的渲染方式,对于Google bot 及访客而言,最初拿到的页面几乎是空白的HTML 档案,随着访客的操作,JavaScript 非同步的产生并下载内容。用料理与食谱来比喻,Google bot 及访客都只拿到了一份食谱,后面呈现端看访客如何烘培蛋糕(操作网站)。
  但是,Google bot 并不像访客一样,会有许多花里胡哨的操作,Google bot 不会滚动、不会点击更不会跟网站进行互动,所以如果你是全CSR(客户端渲染)的页面一定要注意,解决方法如下:
  ①服务器端渲染(SSR)
  敞偌你的页面因为JavaScript 渲染问题导致页面无法被索引,那强烈建议将重要页面或是网站改成服务器端渲染。
  ②动态渲染(Dynamic Rendering )
  有时候当然不可能说全改成SSR ,于是动态渲染就变成当今蛮重要的一种渲染方式,能同时做到CSR 想呈现的效果,又能同时达到SEO 排名。
  从下图可以看到,网页使用了全JavaScript 所产生的内容,但是提供给Google bot 的是另一静态HTML 页面,很好的解决了Google 爬虫无法查看渲染页面的问题。
  以下三种服务可以很好的帮助你实现动态渲染功能:
  Prerender.io
  Puppeteer
  Rendertron #0
  Google 官方文件也提供了转译原理、说明及方式,推荐大家看看。而下图是各种渲染JavaScript 的方法,其实大部分对于Google 来说都是渲染的出来的,比较难的还是在CSR(客户端渲染)的部分,所以如果你是CSR 建议导入动态渲染喔。
  六、如何建构一个友善SEO 的JavaScript 网站
  其实这个小节的内容有部分你可能过去就知道了,但因为JavaScript 的关系仍有部分不同。
  允许Google 爬取
  如果连网页都不能爬取、渲染的JavaScript 资源都无法读取的话,就不用说要排名啰,记得Robots.txt里不要禁止渲染相关资源,在Robots.txt中加入以下指令:
  User-Agent: Googlebot
  Allow: .js
  Allow: .css
  On-page 优化
  基本上on-page 上的重要元素应该都要能够被呈现出来,记得透过网址审查工具仔细检查是否都有出现:
  JavaScript 网站最常出现的一个状况是重复Title/Description 被重复使用,记得可以从Google Search Console 中的涵盖范围查看,又或者透过Screaming Frog 等工具确认。
  网址的点击
  前面虽然都有提到,但这边还是正式说明一下,在2018 年的Google I/O 大会上便说到,因为Googlebot 并不会去点击、滚动或是与网页做互动,所以如果你的链接是以onclick 的方式呈现的话,将不会被Googlebot 所爬取。
  对Google 而言,好链接与坏链接
  同样的,在导航上、分页上、内容上一样切记要使用 的方式去呈现链接,才能确保Google 会发现并爬取你的链接。
  网址的更新
  对于部分网页采用SPA(Single Page Application)方式所呈现的网页,在更新网页时,必须使用History API,对于较早期的开发者而言,在更新网页Url 时采用的是片段(fragement)的方式,那网址就会变成我们常见的锚点,如下:
  Our products
  但以『#』这种形式的连结对于Google 来说并不会抓取喔!虽然早期开发出一种连结形式,将『#』取代成『#!』,但这种方式已经过时了,网址也会变得相当丑。
  但是透过History API 的方式就能让网页资讯变动时,链接才会变换成Google 可爬取的形式,完整介绍可参考Google 官方文件。
  错误页面
  因为JavaScript 框架是客户端而非伺服务器端,所以像是当SPA 页面产生错误时,并没有办法传递出404 状态码到服务器中,此时请采取以下其中一种方式解决:
  l使用JavaScript 转移到你原本就设定好404 状态码及页面不存在讯息之页面
  l将错误页面加上noindex 标签,并在页面上呈现『404 页面错误』信息,这样子页面就能被视作软404(soft 404)的状态。
  Sitemap
  我们可能因为使用JavaScript 产生了网站的许多内容,并没有办法说一次到位,解决所有JavaScript 产生的SEO 问题,此时Sitemap.xml 有着重要的角色,就是告知Google 网站重要的页面有哪些,对于你提交的页面,Google 可能会优先爬取。
  但同时,你也必须确保Sitemap 上的所有页面链接没有以下问题:
  重复内容
  被canonical 指到别的页面
  404 错误页面
  301 转址到其它页面
  空白页面
  等等…
  这样Sitemap 才能真正的发挥他的作用,让Google 知道你重要的页面。
  总结
  JavaScript 所产生的内容,已经不像过往几年Google 爬虫完全无法理解,随着开发技术的进步JavaScript 也成为网页开发的重要元素,所以不要急着排斥它。
  记得首先,让Google 能够渲染出你的页面;其次,确认Google 有顺利索引你的页面;接着,按着你一般优化SEO 的方式,排除重复内容、优化内容,加强关键字排名。
  这看似简单的几个步骤就花了很大一个篇幅在说明了,所以一起努力建立一个友善SEO 的JavaScript 网站吧!
  参考资料:
  l了解JavaScript 搜寻引擎最佳化(SEO) 基础知识
  l修正会影响搜寻体验的JavaScript 问题
  l导入动态转译
  lRendering on the Web
  lJavaScript SEO: What You Need to Know
  lThe Ultimate Guide to JavaScript SEO (2020 Edition)
  lJavaScript and SEO: The Difference Between Crawling and Indexing
  lMaking JavaScript and Google Search work together
  lRendering SEO manifesto – why JavaScript SEO is not enough
  lJavaScript vs. Crawl Budget: Ready Player One
  lEverything You Know About JavaScript Indexing is Wrong
  lStatic vs. Server Rendering
  lDeliver search-friendly JavaScript-powered websites (Google I/O '18)
  lJavaScript SEO – How Does Google Crawl JavaScript

js提取指定网站内容 真香系列-JSFinder实用改造

网站优化优采云 发表了文章 • 0 个评论 • 85 次浏览 • 2022-06-28 14:27 • 来自相关话题

  js提取指定网站内容 真香系列-JSFinder实用改造
  点击上方蓝字关注我吧!
  1.前言
  JSFinder是一款优秀的github开源工具,这款工具功能就是查找隐藏在js文件中的api接口和敏感目录,以及一些子域名。
  github链接:https://github.com/Threezh1/JSFinder
  用于提取的正则表达式参考了LinkFinder
  SFinder获取URL和子域名的方式:
  一些简单的使用方式:
  简单爬取
  python JSFinder.py -u http://www.mi.com<br />#这个命令会爬取 http://www.mi.com 这单个页面的所有的js链接,并在其中发现url和子域名
  深度爬取
  python JSFinder.py -u http://www.mi.com -d<br />#深入一层页面爬取JS,时间会消耗的更长,建议使用-ou 和 -os来指定保存URL和子域名的文件名python JSFinder.py -u http://www.mi.com -d -ou mi_url.txt -os mi_subdomain.txt
  批量指定URL/指定JS
  指定URL:
  python JSFinder.py -f text.txt
  指定JS:
  
  python JSFinder.py -f text.txt -j
  可以用brupsuite爬取网站后提取出URL或者JS链接,保存到txt文件中,一行一个。
  指定URL或JS就不需要加深度爬取,单个页面即可,等等,这可以去github上面看使用说明。
  2.改造
  2.1 为什么要改造这个东西?
  因为我经常使用这款工具,我发现了很多不足之处,比如说,如果爬取一个大型一点的,会发现很多url,接口,但是大多数都是404,没有用处的,就是通过人工去筛选就得费好长一段时间,我有一次爬下来了1200多条,密密麻麻............................
  所有我的设想是可以增加一个验证模块,进行简单的验证,扔掉那些不存在的url链接,减少人工的筛选。
  2.2 找到源码一顿改(验证模块)
  改源码一定要找到关键点改,我这里直接在它进行数据处理的时候加入我想要的东西:
   thread_num = 0 info = '访问成功' lock = threading.Lock() if urls == None: return None find_url_all_num = len(urls) content_url = "" content_subdomain = "" if self.args.verify !=0: print("A total of Find " + str(len(urls)) + " URL:\n") print("-----------------------But further validation is needed-----------------!\n\n\n") domian_text = requests.get(domian,verify =False).text print("The length of the page currently visited =>"+str(len(domian_text))) result ={} for url in urls: thread_num += 1 self.therads_op(url, content_url, lock,thread_num,result) if thread_num == 100: time.sleep(1) find_url_success_num = 0 for length,url_list in result.items(): print("-----------------------The return packet length is :{len}------------------------".format(len =length)) for url in url_list: print(url+"\n") find_url_success_num += 1 content_url+=url+"\n"
  关键的一些代码,这里因为使用了网络验证,所以写了个多线程:
   def therads_op(self,url,content_url,lock,thread_num,result): threading.Thread(target=self.request(url,content_url,lock,result),args=(url,content_url,lock,result,)) if lock.acquire(): thread_num -= 1 lock.release()
  验证模块:
  def request(self,url,content_url,lock,result): headers = { "User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", } try: resp = requests.get(url,verify = False,timeout = 10,headers=headers) if resp.status_code != 404 and lock.acquire(): content_url += url + "\n" if result.get(str(len(resp.text)), 0) == 0: result[str(len(resp.text))] = [] result[str(len(resp.text))].append(url) else: result[str(len(resp.text))].append(url) lock.release()<br /> except Exception as e: pass finally: try: lock.release() except RuntimeError as e: pass
  这里我是直接判断它返回值是不是404,当然你也可以加入你自己的判断条件,可以看到我的源码里,有计数返回包的长度,因为我发现很多包的返回包都是一样的,所以我这里判断长度,进行归类,有利于我们自己人工筛选,我们只需要得到任意长度的一个url返回包,就可以知道其他有着相同长度的url返回的内容(这就是我当时的想法吧)
  2.3 找到源码一阵改(输出数据格式)
  因为原工具是有把输出结果输出到一个文件的功能,但是我感觉不够直观,所以我把输出结果转换成了html文件,可以直接点击url,进行访问,方便了很多。
  if self.args.output_html !=None: table_tr0 = '' html = html_Template() total_str = '共url: %s,访问成功:%s,失败 %s' % (find_url_all_num, find_url_success_num, find_url_all_num-find_url_success_num) if self.args.verify !=0: for length,url_list in result.items(): for url in url_list: url_a = "<a href={url}>点击</a>".format(url=url) table_td = html.TABLE_TMPL % dict(length=length, url=url, result=info, ask_url=url_a, ) table_tr0 += table_td else: for url in urls: url_a = "<a href={url}>点击</a>".format(url=url) table_td = html.TABLE_TMPL % dict(length="无法获取", url=url, result=info, ask_url=url_a, ) table_tr0 += table_td output = html.HTML_TMPL % dict(domain=self.args.url,value=total_str, table_tr=table_tr0, ) # 生成html报告 filename = '{date}_{url}.html'.format(date=time.strftime('%Y%m%d%H%M%S'),url = self.args.output_html) dir = str(os.getcwd()) filename = os.path.join(dir, filename) with open(filename, 'wb') as f: f.write(bytes(output, "utf-8"))
  
  我把源码改成了一个类的形式,有利于以后的加入到大项目中,积小成多!
  2.4 效果预览
  在没有加验证参数的情况下:
  开启验证的情况下:
  3.总结
  本来还想加一个爬虫模块进去的,但是作者有自己的爬虫模块,就算了,如果可以的话,也可以把一些优秀的开源爬虫加进去,就真的很nice了,我以后再加把,先这样吧,运行有什么问题可以及时联系我,越改越实用。
  挺香的!真香,找个机会把源码放到github上面去:
  exe程序百度云链接:
  链接:https://pan.baidu.com/s/17WIa94fr5EAHgfo4UI6Eyw 提取码:qq0c 复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V3的分享
  END
  看完记得点赞,关注哟,爱您!
  请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付! 查看全部

  js提取指定网站内容 真香系列-JSFinder实用改造
  点击上方蓝字关注我吧!
  1.前言
  JSFinder是一款优秀的github开源工具,这款工具功能就是查找隐藏在js文件中的api接口和敏感目录,以及一些子域名。
  github链接:https://github.com/Threezh1/JSFinder
  用于提取的正则表达式参考了LinkFinder
  SFinder获取URL和子域名的方式:
  一些简单的使用方式:
  简单爬取
  python JSFinder.py -u http://www.mi.com<br />#这个命令会爬取 http://www.mi.com 这单个页面的所有的js链接,并在其中发现url和子域名
  深度爬取
  python JSFinder.py -u http://www.mi.com -d<br />#深入一层页面爬取JS,时间会消耗的更长,建议使用-ou 和 -os来指定保存URL和子域名的文件名python JSFinder.py -u http://www.mi.com -d -ou mi_url.txt -os mi_subdomain.txt
  批量指定URL/指定JS
  指定URL:
  python JSFinder.py -f text.txt
  指定JS:
  
  python JSFinder.py -f text.txt -j
  可以用brupsuite爬取网站后提取出URL或者JS链接,保存到txt文件中,一行一个。
  指定URL或JS就不需要加深度爬取,单个页面即可,等等,这可以去github上面看使用说明。
  2.改造
  2.1 为什么要改造这个东西?
  因为我经常使用这款工具,我发现了很多不足之处,比如说,如果爬取一个大型一点的,会发现很多url,接口,但是大多数都是404,没有用处的,就是通过人工去筛选就得费好长一段时间,我有一次爬下来了1200多条,密密麻麻............................
  所有我的设想是可以增加一个验证模块,进行简单的验证,扔掉那些不存在的url链接,减少人工的筛选。
  2.2 找到源码一顿改(验证模块)
  改源码一定要找到关键点改,我这里直接在它进行数据处理的时候加入我想要的东西:
   thread_num = 0 info = '访问成功' lock = threading.Lock() if urls == None: return None find_url_all_num = len(urls) content_url = "" content_subdomain = "" if self.args.verify !=0: print("A total of Find " + str(len(urls)) + " URL:\n") print("-----------------------But further validation is needed-----------------!\n\n\n") domian_text = requests.get(domian,verify =False).text print("The length of the page currently visited =>"+str(len(domian_text))) result ={} for url in urls: thread_num += 1 self.therads_op(url, content_url, lock,thread_num,result) if thread_num == 100: time.sleep(1) find_url_success_num = 0 for length,url_list in result.items(): print("-----------------------The return packet length is :{len}------------------------".format(len =length)) for url in url_list: print(url+"\n") find_url_success_num += 1 content_url+=url+"\n"
  关键的一些代码,这里因为使用了网络验证,所以写了个多线程:
   def therads_op(self,url,content_url,lock,thread_num,result): threading.Thread(target=self.request(url,content_url,lock,result),args=(url,content_url,lock,result,)) if lock.acquire(): thread_num -= 1 lock.release()
  验证模块:
  def request(self,url,content_url,lock,result): headers = { "User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", } try: resp = requests.get(url,verify = False,timeout = 10,headers=headers) if resp.status_code != 404 and lock.acquire(): content_url += url + "\n" if result.get(str(len(resp.text)), 0) == 0: result[str(len(resp.text))] = [] result[str(len(resp.text))].append(url) else: result[str(len(resp.text))].append(url) lock.release()<br /> except Exception as e: pass finally: try: lock.release() except RuntimeError as e: pass
  这里我是直接判断它返回值是不是404,当然你也可以加入你自己的判断条件,可以看到我的源码里,有计数返回包的长度,因为我发现很多包的返回包都是一样的,所以我这里判断长度,进行归类,有利于我们自己人工筛选,我们只需要得到任意长度的一个url返回包,就可以知道其他有着相同长度的url返回的内容(这就是我当时的想法吧)
  2.3 找到源码一阵改(输出数据格式)
  因为原工具是有把输出结果输出到一个文件的功能,但是我感觉不够直观,所以我把输出结果转换成了html文件,可以直接点击url,进行访问,方便了很多。
  if self.args.output_html !=None: table_tr0 = '' html = html_Template() total_str = '共url: %s,访问成功:%s,失败 %s' % (find_url_all_num, find_url_success_num, find_url_all_num-find_url_success_num) if self.args.verify !=0: for length,url_list in result.items(): for url in url_list: url_a = "<a href={url}>点击</a>".format(url=url) table_td = html.TABLE_TMPL % dict(length=length, url=url, result=info, ask_url=url_a, ) table_tr0 += table_td else: for url in urls: url_a = "<a href={url}>点击</a>".format(url=url) table_td = html.TABLE_TMPL % dict(length="无法获取", url=url, result=info, ask_url=url_a, ) table_tr0 += table_td output = html.HTML_TMPL % dict(domain=self.args.url,value=total_str, table_tr=table_tr0, ) # 生成html报告 filename = '{date}_{url}.html'.format(date=time.strftime('%Y%m%d%H%M%S'),url = self.args.output_html) dir = str(os.getcwd()) filename = os.path.join(dir, filename) with open(filename, 'wb') as f: f.write(bytes(output, "utf-8"))
  
  我把源码改成了一个类的形式,有利于以后的加入到大项目中,积小成多!
  2.4 效果预览
  在没有加验证参数的情况下:
  开启验证的情况下:
  3.总结
  本来还想加一个爬虫模块进去的,但是作者有自己的爬虫模块,就算了,如果可以的话,也可以把一些优秀的开源爬虫加进去,就真的很nice了,我以后再加把,先这样吧,运行有什么问题可以及时联系我,越改越实用。
  挺香的!真香,找个机会把源码放到github上面去:
  exe程序百度云链接:
  链接:https://pan.baidu.com/s/17WIa94fr5EAHgfo4UI6Eyw 提取码:qq0c 复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V3的分享
  END
  看完记得点赞,关注哟,爱您!
  请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付!

JS逆向:滑块验证码加密分析

网站优化优采云 发表了文章 • 0 个评论 • 315 次浏览 • 2022-06-23 11:36 • 来自相关话题

  JS逆向:滑块验证码加密分析
  为什么要做逆向?动态网页爬虫一般可分为两种:Selenium爬取和接口爬取。
  两种方式各有优缺点:
  前者我们己经介绍了selenium的使用和验证码、滑块的使用,其虽然可以很好地处理网页异步加载问题,但面对大型爬虫任务时,效率还是比较低的;
  后者虽然爬取速度较快,但请求参数很可能是动态变化的,这时就需要利用一些前端的知识,重新构造参数,整个过程通常称为JS逆向。
  先来看一下简单的请求:
  
  但是往往在我们编写爬虫时,可能会碰到以下两种问题:造成这种问题原因是,你所正在爬取的页面采取了动态加载的方式动态加载网页其显示的页面则是经过Javascript处理数据后生成的结果,可以发生改变。
  JavaScript是一种运行在浏览器中的解释型编程语言,JavaScript非常值得学习,它既适合作为学习编程的入门语言,也适合当作日常开发的工作语言。
  JavaScript可以收集用户的跟踪数据,不需要重载页面即可直接提交表单,可在页面中嵌入多媒体文件,甚至可以运行网页游戏等。在很多看起来非常简单的页面背后通常使用了许多JavaScript文件。比如:
  
  这些数据的来源有多种,可能是经过Javascript计算生成的,也可能是通过Ajax加载的。Ajax = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),其最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页的内容。
  逆向工程
  对于动态加载的网页,我们想要获取其网页数据,需要了解网页是如何加载数据的,该过程就被成为逆向工程。
  对于使用了Ajax 请求技术的网页,我们可以找到Ajax请求的具体链接,直接得到Ajax请求得到的数据。
  需要注意的是,构造Ajax请求有两种方式:
  原生的Ajax请求,会直接创建一个XMLHTTPRequest对象。
  调用jQuery的ajax()方法。一般情况下,.ajax()会返回其创建的XMLHTTPRequest对象;但是,如果.ajax()的dataType参数指定了为script或jsonp类型,.ajax()不再返回其创建的XMLHTTPRequest对象。
  JQuery补充:
  在大型互联网公司的不断推广下,JavaScript生态圈也在不断的完善,各种类库、API接口层出不穷。
  jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“Write Less,Do More”,即倡导写更少的代码,做更多的事情。
  对于这两种方式,只要创建返回了XMLHTTPRequest对象,就可以通过Chrome浏览器的调试工具在NetWork窗口通过设置XHR过滤条件,直接筛选出Ajax请求的链接;如果是$.ajax()并且dataType指定了为script或jsonp,则无法通过这种方式筛选出来。
  案例分析
  这次搞得还是滑块哦,话不多说直接开搞数美滑块,因为小红书、蘑菇街、脉脉、斗鱼等很多都用了数美的验证码。整体难度还可以就是动态参数有点东西的呢!
  数美验证码官网:
  
  数美滑块的验证码主要的难点有以下几点:
  1.request的请求参数,是动态变化的。名称是动态变化,加密的密钥也是动态变化的,这就有点难搞了
  2.每天小版本更新的频率1-2次,必须得能够实现完全自动化,否则人工很难及时的调整验证码的参数,来不及。
  3.js里的混淆的变量也是动态变化的
  验证码注册
  先看一下register
  
  下图是响应结果:bg和fg是验证码图片地址 bg
  计算滑块位置
  根据上一步可以得到验证图片的地址。
  验证码图片:
  滑块图片:
  使用opencv查找并匹配图像模板中的滑块。
  需要注意的是,这里是以原图计算的,而页面上的图片大小只有(300,150),(应用不同的产品可能大小也不同) 所以需要按比例进行缩小或者放大。
  验证
  对应的api地址是:
  查询字符串参数:
  params参数里的 dv,qe,ou,cf等等,都经过了DES加密。
  破解方式分析
  打开控制台多看几遍请求过程,我们基本就明白请求步骤了。具体的分析过程就不再赘述。
  所携带的请求参数如下:
  
  该接口返回的js参数,是下一步需要请求的目标。
  提取js参数
  js地址:
  需要提取该js中的参数名,会在最后验证的时候使用(注:一般情况下参数名不会变),但是这些请求参数都是变化的。
  获取js的response,搜索上面的参数我们没有找到,但是发现了倒序的名字
  
  通过查看调用栈,打断点,一层层分析,发现js做了ob混淆。
  JS混淆有很多种,这里举几个:UglifyJS,JScrambler,,JSDetox,obfuscator.io 等,像下面的代码就是ob混淆。
  开头定义了一个大数组,然后对这个大数组里的内容进行位移,再定义一个解密函数。后面大部分的值都调用了这个解密函数,以达到混淆的效果。如果想还原可以使用ob混淆还原工具:
  
  当然不进行混淆还原也可以通过断点很快的定位到具体的函数加密的位置
  再次请求走到这里,而这里是一部分的参数的加密,先进去看下它是怎么加密的
  
  进来了走到这可以看到是DES加密,参数分别是加密的密码,要加密的参数,后面两个是数字呢就是模式选择了,1,0是加密,0,0是解密,在这里是加密。
  我们输出在console中输出一下,这四个参数看一下
  
  那么问题来了,这个密码"b64ccadf"哪来的呢,别急,我们重新再来一遍!很快我们又进来走到这,_0x1c2865是什么怎么是乱码的呢?
  
  console输出一下看看
  
  密码搞到了,加密方式也晓得了,然后参数一个一个整过去就Ok了。
  返回结果response:
  message = success,riskLevel=PASS 说明验证通过
  完整代码
<p>"""<br />数美滑块验证码破解验证<br />"""<br /><br />import base64<br />import json<br />import random<br />import re<br />import time<br />from io import BytesIO<br />import cv2<br />import numpy as np<br />import requests<br />from pyDes import des, ECB<br /><br />CAPTCHA_DISPLAY_WIDTH = 310<br />CAPTCHA_DISPLAY_HEIGHT = 155<br /><br />p = {}<br /><br /><br />def pad(b):<br />    """<br />    块填充<br />    """<br />    block_size = 8<br />    while len(b) % block_size:<br />        b += b'\0'<br />    return b<br /><br /><br />def split_args(s):<br />    """<br />    分割js参数<br />    """<br />    r = []<br />    a = ''<br />    i = 0<br />    while i  100:<br />            a = split_args(r)<br />            break<br /><br />    r = re.search(r';\)(.*?)\(}', script[::-1]).group(1)<br />    v = split_args(r[::-1])<br /><br />    d = r'{%s}' % ''.join([((',' if i else '') + '\'k{}\':([_x0-9a-z]*)'.format(i + 1)) for i in range(15)])<br /><br />    k = []<br />    r = re.search(d, script)<br />    for i in range(15):<br />        k.append(r.group(i + 1))<br /><br />    n = int(v[a.index(re.search(r'arguments;.*?,(.*?)\);', script).group(1))], base=16)<br /><br />    for i in range(n // 2):<br />        v[i], v[n - 1 - i] = v[n - 1 - i], v[i]<br /><br />    for i, b in enumerate(k):<br />        t = v[a.index(b)].strip('\'')<br />        names['k{}'.format(i + 1)] = t if len(t) > 2 else t[::-1]<br /><br />    return names<br /><br /><br />def get_encrypt_content(message, key, flag):<br />    """<br />    接口参数的加密、解密<br />    """<br />    des_obj = des(key.encode(), mode=ECB)<br />    if flag:<br />        content = pad(str(message).replace(' ', '').encode())<br />        return base64.b64encode(des_obj.encrypt(content)).decode('utf-8')<br />    else:<br />        return des_obj.decrypt(base64.b64decode(message)).decode('utf-8')<br /><br /><br />def get_random_ge(distance):<br />    """<br />    生成随机的轨迹<br />    """<br />    ge = []<br /><br />    y = 0<br />    v = 0<br />    t = 1<br />    current = 0<br />    mid = distance * 3 / 4<br />    exceed = 20<br />    z = t<br /><br />    ge.append([0, 0, 1])<br /><br />    while current  查看全部

  JS逆向:滑块验证码加密分析
  为什么要做逆向?动态网页爬虫一般可分为两种:Selenium爬取和接口爬取。
  两种方式各有优缺点:
  前者我们己经介绍了selenium的使用和验证码、滑块的使用,其虽然可以很好地处理网页异步加载问题,但面对大型爬虫任务时,效率还是比较低的;
  后者虽然爬取速度较快,但请求参数很可能是动态变化的,这时就需要利用一些前端的知识,重新构造参数,整个过程通常称为JS逆向。
  先来看一下简单的请求:
  
  但是往往在我们编写爬虫时,可能会碰到以下两种问题:造成这种问题原因是,你所正在爬取的页面采取了动态加载的方式动态加载网页其显示的页面则是经过Javascript处理数据后生成的结果,可以发生改变。
  JavaScript是一种运行在浏览器中的解释型编程语言,JavaScript非常值得学习,它既适合作为学习编程的入门语言,也适合当作日常开发的工作语言。
  JavaScript可以收集用户的跟踪数据,不需要重载页面即可直接提交表单,可在页面中嵌入多媒体文件,甚至可以运行网页游戏等。在很多看起来非常简单的页面背后通常使用了许多JavaScript文件。比如:
  
  这些数据的来源有多种,可能是经过Javascript计算生成的,也可能是通过Ajax加载的。Ajax = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),其最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页的内容。
  逆向工程
  对于动态加载的网页,我们想要获取其网页数据,需要了解网页是如何加载数据的,该过程就被成为逆向工程。
  对于使用了Ajax 请求技术的网页,我们可以找到Ajax请求的具体链接,直接得到Ajax请求得到的数据。
  需要注意的是,构造Ajax请求有两种方式:
  原生的Ajax请求,会直接创建一个XMLHTTPRequest对象。
  调用jQuery的ajax()方法。一般情况下,.ajax()会返回其创建的XMLHTTPRequest对象;但是,如果.ajax()的dataType参数指定了为script或jsonp类型,.ajax()不再返回其创建的XMLHTTPRequest对象。
  JQuery补充:
  在大型互联网公司的不断推广下,JavaScript生态圈也在不断的完善,各种类库、API接口层出不穷。
  jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“Write Less,Do More”,即倡导写更少的代码,做更多的事情。
  对于这两种方式,只要创建返回了XMLHTTPRequest对象,就可以通过Chrome浏览器的调试工具在NetWork窗口通过设置XHR过滤条件,直接筛选出Ajax请求的链接;如果是$.ajax()并且dataType指定了为script或jsonp,则无法通过这种方式筛选出来。
  案例分析
  这次搞得还是滑块哦,话不多说直接开搞数美滑块,因为小红书、蘑菇街、脉脉、斗鱼等很多都用了数美的验证码。整体难度还可以就是动态参数有点东西的呢!
  数美验证码官网:
  
  数美滑块的验证码主要的难点有以下几点:
  1.request的请求参数,是动态变化的。名称是动态变化,加密的密钥也是动态变化的,这就有点难搞了
  2.每天小版本更新的频率1-2次,必须得能够实现完全自动化,否则人工很难及时的调整验证码的参数,来不及。
  3.js里的混淆的变量也是动态变化的
  验证码注册
  先看一下register
  
  下图是响应结果:bg和fg是验证码图片地址 bg
  计算滑块位置
  根据上一步可以得到验证图片的地址。
  验证码图片:
  滑块图片:
  使用opencv查找并匹配图像模板中的滑块。
  需要注意的是,这里是以原图计算的,而页面上的图片大小只有(300,150),(应用不同的产品可能大小也不同) 所以需要按比例进行缩小或者放大。
  验证
  对应的api地址是:
  查询字符串参数:
  params参数里的 dv,qe,ou,cf等等,都经过了DES加密。
  破解方式分析
  打开控制台多看几遍请求过程,我们基本就明白请求步骤了。具体的分析过程就不再赘述。
  所携带的请求参数如下:
  
  该接口返回的js参数,是下一步需要请求的目标。
  提取js参数
  js地址:
  需要提取该js中的参数名,会在最后验证的时候使用(注:一般情况下参数名不会变),但是这些请求参数都是变化的。
  获取js的response,搜索上面的参数我们没有找到,但是发现了倒序的名字
  
  通过查看调用栈,打断点,一层层分析,发现js做了ob混淆。
  JS混淆有很多种,这里举几个:UglifyJS,JScrambler,,JSDetox,obfuscator.io 等,像下面的代码就是ob混淆。
  开头定义了一个大数组,然后对这个大数组里的内容进行位移,再定义一个解密函数。后面大部分的值都调用了这个解密函数,以达到混淆的效果。如果想还原可以使用ob混淆还原工具:
  
  当然不进行混淆还原也可以通过断点很快的定位到具体的函数加密的位置
  再次请求走到这里,而这里是一部分的参数的加密,先进去看下它是怎么加密的
  
  进来了走到这可以看到是DES加密,参数分别是加密的密码,要加密的参数,后面两个是数字呢就是模式选择了,1,0是加密,0,0是解密,在这里是加密。
  我们输出在console中输出一下,这四个参数看一下
  
  那么问题来了,这个密码"b64ccadf"哪来的呢,别急,我们重新再来一遍!很快我们又进来走到这,_0x1c2865是什么怎么是乱码的呢?
  
  console输出一下看看
  
  密码搞到了,加密方式也晓得了,然后参数一个一个整过去就Ok了。
  返回结果response:
  message = success,riskLevel=PASS 说明验证通过
  完整代码
<p>"""<br />数美滑块验证码破解验证<br />"""<br /><br />import base64<br />import json<br />import random<br />import re<br />import time<br />from io import BytesIO<br />import cv2<br />import numpy as np<br />import requests<br />from pyDes import des, ECB<br /><br />CAPTCHA_DISPLAY_WIDTH = 310<br />CAPTCHA_DISPLAY_HEIGHT = 155<br /><br />p = {}<br /><br /><br />def pad(b):<br />    """<br />    块填充<br />    """<br />    block_size = 8<br />    while len(b) % block_size:<br />        b += b'\0'<br />    return b<br /><br /><br />def split_args(s):<br />    """<br />    分割js参数<br />    """<br />    r = []<br />    a = ''<br />    i = 0<br />    while i  100:<br />            a = split_args(r)<br />            break<br /><br />    r = re.search(r';\)(.*?)\(}', script[::-1]).group(1)<br />    v = split_args(r[::-1])<br /><br />    d = r'{%s}' % ''.join([((',' if i else '') + '\'k{}\':([_x0-9a-z]*)'.format(i + 1)) for i in range(15)])<br /><br />    k = []<br />    r = re.search(d, script)<br />    for i in range(15):<br />        k.append(r.group(i + 1))<br /><br />    n = int(v[a.index(re.search(r'arguments;.*?,(.*?)\);', script).group(1))], base=16)<br /><br />    for i in range(n // 2):<br />        v[i], v[n - 1 - i] = v[n - 1 - i], v[i]<br /><br />    for i, b in enumerate(k):<br />        t = v[a.index(b)].strip('\'')<br />        names['k{}'.format(i + 1)] = t if len(t) > 2 else t[::-1]<br /><br />    return names<br /><br /><br />def get_encrypt_content(message, key, flag):<br />    """<br />    接口参数的加密、解密<br />    """<br />    des_obj = des(key.encode(), mode=ECB)<br />    if flag:<br />        content = pad(str(message).replace(' ', '').encode())<br />        return base64.b64encode(des_obj.encrypt(content)).decode('utf-8')<br />    else:<br />        return des_obj.decrypt(base64.b64decode(message)).decode('utf-8')<br /><br /><br />def get_random_ge(distance):<br />    """<br />    生成随机的轨迹<br />    """<br />    ge = []<br /><br />    y = 0<br />    v = 0<br />    t = 1<br />    current = 0<br />    mid = distance * 3 / 4<br />    exceed = 20<br />    z = t<br /><br />    ge.append([0, 0, 1])<br /><br />    while current 

Node.js Express 框架

网站优化优采云 发表了文章 • 0 个评论 • 388 次浏览 • 2022-06-23 11:32 • 来自相关话题

  Node.js Express 框架
  接下来我们扩展 Hello World,添加一些功能来处理更多类型的 HTTP 请求。
  创建 express_demo2.js 文件,代码如下所示:
  express_demo2.js 文件代码:
  var express = require('express');var app = express(); // 主页输出 "Hello World"app.get('/', function (req, res) { console.log("主页 GET 请求"); res.send('Hello GET');}) // POST 请求app.post('/', function (req, res) { console.log("主页 POST 请求"); res.send('Hello POST');}) // /del_user 页面响应app.get('/del_user', function (req, res) { console.log("/del_user 响应 DELETE 请求"); res.send('删除页面');}) // /list_user 页面 GET 请求app.get('/list_user', function (req, res) { console.log("/list_user GET 请求"); res.send('用户列表页面');}) // 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求app.get('/ab*cd', function(req, res) { console.log("/ab*cd GET 请求"); res.send('正则匹配');}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node express_demo2.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  接下来你可以尝试访问 :8081 不同的地址,查看效果。
  在浏览器中访问 :8081/list_user,结果如下图所示:
  
  在浏览器中访问 :8081/abcd,结果如下图所示:
  
  在浏览器中访问 :8081/abcdefg,结果如下图所示:
  
  静态文件
  Express 提供了内置的中间件express.static来设置静态文件如:图片, CSS, JavaScript 等。
  你可以使用express.static中间件来设置静态文件路径。例如,如果你将图片, CSS, JavaScript 文件放在 public 目录下,你可以这么写:
  app.use('/public', express.static('public'));
  我们可以到 public/images 目录下放些图片,如下所示:
  node_modules<br />server.js<br />public/public/images<br />public/images/logo.png
  让我们再修改下 "Hello World" 应用添加处理静态文件的功能。
  创建 express_demo3.js 文件,代码如下所示:
  express_demo3.js 文件代码:
  var express = require('express');var app = express(); app.use('/public', express.static('public')); app.get('/', function (req, res) { res.send('Hello World');}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node express_demo3.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  执行以上代码:
  在浏览器中访问 :8081/public/images/logo.png(本实例采用了菜鸟教程的 logo),结果如下图所示:
  
  GET 方法
  以下实例演示了在表单中通过 GET 方法提交两个参数,我们可以使用 server.js 文件内的process_get路由器来处理输入:
  index.html 文件代码:
  First Name: Last Name:
  server.js 文件代码:
  var express = require('express');var app = express(); app.use('/public', express.static('public')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.get('/process_get', function (req, res) { // 输出 JSON 格式 var response = { "first_name":req.query.first_name, "last_name":req.query.last_name }; console.log(response); res.end(JSON.stringify(response));}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  node server.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  POST 方法
  以下实例演示了在表单中通过 POST 方法提交两个参数,我们可以使用 server.js 文件内的process_post路由器来处理输入:
  index.html 文件代码:
  First Name: Last Name:
  server.js 文件代码:
  var express = require('express');var app = express();var bodyParser = require('body-parser'); // 创建 application/x-www-form-urlencoded 编码解析var urlencodedParser = bodyParser.urlencoded({ extended: false }) app.use('/public', express.static('public')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.post('/process_post', urlencodedParser, function (req, res) { // 输出 JSON 格式 var response = { "first_name":req.body.first_name, "last_name":req.body.last_name }; console.log(response); res.end(JSON.stringify(response));}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node server.js<br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  文件上传
  以下我们创建一个用于上传文件的表单,使用 POST 方法,表单 enctype 属性设置为 multipart/form-data。
  index.html 文件代码:
  文件上传表单文件上传:选择一个文件上传:
  server.js 文件代码:
  var express = require('express');var app = express();var fs = require("fs"); var bodyParser = require('body-parser');var multer = require('multer'); app.use('/public', express.static('public'));app.use(bodyParser.urlencoded({ extended: false }));app.use(multer({ dest: '/tmp/'}).array('image')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.post('/file_upload', function (req, res) { console.log(req.files[0]); // 上传的文件信息 var des_file = __dirname + "/" + req.files[0].originalname; fs.readFile( req.files[0].path, function (err, data) { fs.writeFile(des_file, data, function (err) { if( err ){ console.log( err ); }else{ response = { message:'File uploaded successfully', filename:req.files[0].originalname }; } console.log( response ); res.end( JSON.stringify( response ) ); }); });}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node server.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  Cookie 管理
  我们可以使用中间件向 Node.js 服务器发送 cookie 信息,以下代码输出了客户端发送的 cookie 信息:
  express_cookie.js 文件代码:
  // express_cookie.js 文件var express = require('express')var cookieParser = require('cookie-parser')var util = require('util'); var app = express()app.use(cookieParser()) app.get('/', function(req, res) { console.log("Cookies: " + util.inspect(req.cookies));}) app.listen(8081)
  执行以上代码:
  $ node express_cookie.js
  现在你可以访问 :8081 并查看终端信息的输出,如下演示:
  
  相关资料 查看全部

  Node.js Express 框架
  接下来我们扩展 Hello World,添加一些功能来处理更多类型的 HTTP 请求。
  创建 express_demo2.js 文件,代码如下所示:
  express_demo2.js 文件代码:
  var express = require('express');var app = express(); // 主页输出 "Hello World"app.get('/', function (req, res) { console.log("主页 GET 请求"); res.send('Hello GET');}) // POST 请求app.post('/', function (req, res) { console.log("主页 POST 请求"); res.send('Hello POST');}) // /del_user 页面响应app.get('/del_user', function (req, res) { console.log("/del_user 响应 DELETE 请求"); res.send('删除页面');}) // /list_user 页面 GET 请求app.get('/list_user', function (req, res) { console.log("/list_user GET 请求"); res.send('用户列表页面');}) // 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求app.get('/ab*cd', function(req, res) { console.log("/ab*cd GET 请求"); res.send('正则匹配');}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node express_demo2.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  接下来你可以尝试访问 :8081 不同的地址,查看效果。
  在浏览器中访问 :8081/list_user,结果如下图所示:
  
  在浏览器中访问 :8081/abcd,结果如下图所示:
  
  在浏览器中访问 :8081/abcdefg,结果如下图所示:
  
  静态文件
  Express 提供了内置的中间件express.static来设置静态文件如:图片, CSS, JavaScript 等。
  你可以使用express.static中间件来设置静态文件路径。例如,如果你将图片, CSS, JavaScript 文件放在 public 目录下,你可以这么写:
  app.use('/public', express.static('public'));
  我们可以到 public/images 目录下放些图片,如下所示:
  node_modules<br />server.js<br />public/public/images<br />public/images/logo.png
  让我们再修改下 "Hello World" 应用添加处理静态文件的功能。
  创建 express_demo3.js 文件,代码如下所示:
  express_demo3.js 文件代码:
  var express = require('express');var app = express(); app.use('/public', express.static('public')); app.get('/', function (req, res) { res.send('Hello World');}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node express_demo3.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  执行以上代码:
  在浏览器中访问 :8081/public/images/logo.png(本实例采用了菜鸟教程的 logo),结果如下图所示:
  
  GET 方法
  以下实例演示了在表单中通过 GET 方法提交两个参数,我们可以使用 server.js 文件内的process_get路由器来处理输入:
  index.html 文件代码:
  First Name: Last Name:
  server.js 文件代码:
  var express = require('express');var app = express(); app.use('/public', express.static('public')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.get('/process_get', function (req, res) { // 输出 JSON 格式 var response = { "first_name":req.query.first_name, "last_name":req.query.last_name }; console.log(response); res.end(JSON.stringify(response));}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  node server.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  POST 方法
  以下实例演示了在表单中通过 POST 方法提交两个参数,我们可以使用 server.js 文件内的process_post路由器来处理输入:
  index.html 文件代码:
  First Name: Last Name:
  server.js 文件代码:
  var express = require('express');var app = express();var bodyParser = require('body-parser'); // 创建 application/x-www-form-urlencoded 编码解析var urlencodedParser = bodyParser.urlencoded({ extended: false }) app.use('/public', express.static('public')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.post('/process_post', urlencodedParser, function (req, res) { // 输出 JSON 格式 var response = { "first_name":req.body.first_name, "last_name":req.body.last_name }; console.log(response); res.end(JSON.stringify(response));}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node server.js<br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  文件上传
  以下我们创建一个用于上传文件的表单,使用 POST 方法,表单 enctype 属性设置为 multipart/form-data。
  index.html 文件代码:
  文件上传表单文件上传:选择一个文件上传:
  server.js 文件代码:
  var express = require('express');var app = express();var fs = require("fs"); var bodyParser = require('body-parser');var multer = require('multer'); app.use('/public', express.static('public'));app.use(bodyParser.urlencoded({ extended: false }));app.use(multer({ dest: '/tmp/'}).array('image')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.post('/file_upload', function (req, res) { console.log(req.files[0]); // 上传的文件信息 var des_file = __dirname + "/" + req.files[0].originalname; fs.readFile( req.files[0].path, function (err, data) { fs.writeFile(des_file, data, function (err) { if( err ){ console.log( err ); }else{ response = { message:'File uploaded successfully', filename:req.files[0].originalname }; } console.log( response ); res.end( JSON.stringify( response ) ); }); });}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node server.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  Cookie 管理
  我们可以使用中间件向 Node.js 服务器发送 cookie 信息,以下代码输出了客户端发送的 cookie 信息:
  express_cookie.js 文件代码:
  // express_cookie.js 文件var express = require('express')var cookieParser = require('cookie-parser')var util = require('util'); var app = express()app.use(cookieParser()) app.get('/', function(req, res) { console.log("Cookies: " + util.inspect(req.cookies));}) app.listen(8081)
  执行以上代码:
  $ node express_cookie.js
  现在你可以访问 :8081 并查看终端信息的输出,如下演示:
  
  相关资料

事实:自媒体运营需要转什么,所以我就把我这几天

网站优化优采云 发表了文章 • 0 个评论 • 88 次浏览 • 2022-09-21 11:07 • 来自相关话题

  事实:自媒体运营需要转什么,所以我就把我这几天
  js提取指定网站内容:这几天很多同学私信问我现在自媒体运营需要转什么,所以我就把我这几天关于这个问题的测试记录给大家分享一下:我自己测试,更新的时间就是2019.08.02号,文章数量是40篇,这种很像上班时间的分享又像某宝发货的提货提醒,反正你自己判断。在videotap看了一下全网的收益情况。同样一篇文章我在5年前看是每个月2000多,5年后转2018063100。
  
  同样的也是和今日头条一样三倍速度的翻阅。但是这样的效果依然很低,因为你得转100多篇才算完全转换,但是现在我们都很快地完成了一万篇,我同样也看了很多号做做点什么就10w+了。通过我个人观察和计算的情况,效果和收益差距很大很大很大。我刚看完可以推算出几个问题,这些问题都是转化的大小决定的。第一个问题:收益差距决定了你现在需要什么,如果你是要广告收益为主的话,你就需要多多的后期推广来获取收益,不能仅仅依靠前期积累的这些网站内容来提升收益。
  这个收益和自媒体运营又有很大的关系,要么是个人有大量的时间做内容,要么你有能力推广和投放广告,所以这个是有相互影响。第二个问题:你还要看转换率。就是你的收益和你的粉丝数量比值。当你的粉丝量积累达到了一定的量级,你的转换率达到了100%。当你的转换率在100%时候,你的收益就很恐怖。好多账号也是到这个程度,可能一篇文章也没有关注量。
  
  可能一篇文章也没有百度收录。那么这个就是你的转换率决定的。很多号是转化率需要一定的才可以触发收益,也就是说,你转换率达到100%以上才会有收益,如果达不到100%,你的收益就不多。第三个问题:你还要看粉丝数量、平台流量的占比。通过videotap我们看了下网站的阅读量,通过哪个点击量、哪个关键词,阅读量最高。
  这个就很好的决定了你转换率。可能今日头条就是因为一些其他原因转换率特别高。所以你有时间测试就可以通过上面的情况去判断平台的流量占比。因为现在很多网站已经能直接帮助你来测试你的文章是否有收益了。比如我同时测试了百家号和企鹅号。测试平台二者会按照你发布文章的先后来做阅读量的掉。先是百家号,掉的量比企鹅号更多。
  但是很有意思的一个情况,企鹅号掉的更快,而百家号呢,反而降低了。这是文章的转换率高低和网站的占比决定的。欢迎一起交流、沟通、思考。 查看全部

  事实:自媒体运营需要转什么,所以我就把我这几天
  js提取指定网站内容:这几天很多同学私信问我现在自媒体运营需要转什么,所以我就把我这几天关于这个问题的测试记录给大家分享一下:我自己测试,更新的时间就是2019.08.02号,文章数量是40篇,这种很像上班时间的分享又像某宝发货的提货提醒,反正你自己判断。在videotap看了一下全网的收益情况。同样一篇文章我在5年前看是每个月2000多,5年后转2018063100。
  
  同样的也是和今日头条一样三倍速度的翻阅。但是这样的效果依然很低,因为你得转100多篇才算完全转换,但是现在我们都很快地完成了一万篇,我同样也看了很多号做做点什么就10w+了。通过我个人观察和计算的情况,效果和收益差距很大很大很大。我刚看完可以推算出几个问题,这些问题都是转化的大小决定的。第一个问题:收益差距决定了你现在需要什么,如果你是要广告收益为主的话,你就需要多多的后期推广来获取收益,不能仅仅依靠前期积累的这些网站内容来提升收益。
  这个收益和自媒体运营又有很大的关系,要么是个人有大量的时间做内容,要么你有能力推广和投放广告,所以这个是有相互影响。第二个问题:你还要看转换率。就是你的收益和你的粉丝数量比值。当你的粉丝量积累达到了一定的量级,你的转换率达到了100%。当你的转换率在100%时候,你的收益就很恐怖。好多账号也是到这个程度,可能一篇文章也没有关注量。
  
  可能一篇文章也没有百度收录。那么这个就是你的转换率决定的。很多号是转化率需要一定的才可以触发收益,也就是说,你转换率达到100%以上才会有收益,如果达不到100%,你的收益就不多。第三个问题:你还要看粉丝数量、平台流量的占比。通过videotap我们看了下网站的阅读量,通过哪个点击量、哪个关键词,阅读量最高。
  这个就很好的决定了你转换率。可能今日头条就是因为一些其他原因转换率特别高。所以你有时间测试就可以通过上面的情况去判断平台的流量占比。因为现在很多网站已经能直接帮助你来测试你的文章是否有收益了。比如我同时测试了百家号和企鹅号。测试平台二者会按照你发布文章的先后来做阅读量的掉。先是百家号,掉的量比企鹅号更多。
  但是很有意思的一个情况,企鹅号掉的更快,而百家号呢,反而降低了。这是文章的转换率高低和网站的占比决定的。欢迎一起交流、沟通、思考。

js提取指定网站内容-苏州安嘉匹配率500%

网站优化优采云 发表了文章 • 0 个评论 • 88 次浏览 • 2022-09-08 19:16 • 来自相关话题

  js提取指定网站内容-苏州安嘉匹配率500%
  js提取指定网站内容
  一、前言提取是api调用的最基本的一步。在应用程序中,经常需要读取网页,或者更有可能的是对网页进行页面上的内容提取。采用调用javascript的方式进行提取,javascript是从网页中获取动态响应,从而能够从javascript请求网页中的更多数据,转而对网页进行静态化,呈现于页面之中。
  
  采用javascript进行这种提取一般需要以下几步:
  1、读取网页,并匹配重定向http头获取body流,获取响应page_url。在获取响应body流的page_url后,遍历整个网页,依次匹配相应的body流,并计算出提取结果。
  2、读取提取结果,将提取结果依次放置到对应的javascript中,并计算出提取值的base64编码。
  
  3、将提取值转换为base64编码的javascript文件。根据base64编码结果,可以计算出被提取的图片链接。
  二、提取规则总体思路:从0开始,给重定向http头匹配正则表达式,计算出匹配率,通过http头约束,根据不同的匹配率分配不同的抓取规则,将匹配链接中的内容提取。例如:匹配率低于70%时,则不进行抓取。只抓取匹配率达到70%以上的规则,将该规则提取出来。
  1、正则提取匹配率http头规则::正则表达式匹配上限:500^^$一次通用问题的目标链接:/input/a#innerhtml匹配率500%*imgfor://user-agent:''*imgfor://user-agent:''*server:''*input://source=''*offset://http/input*img://user-agent:''*input://user-agent:''*text://user-agent:''*input://user-agent:''*input://inputis://(site:''*)*regexp://*sites://***。 查看全部

  js提取指定网站内容-苏州安嘉匹配率500%
  js提取指定网站内容
  一、前言提取是api调用的最基本的一步。在应用程序中,经常需要读取网页,或者更有可能的是对网页进行页面上的内容提取。采用调用javascript的方式进行提取,javascript是从网页中获取动态响应,从而能够从javascript请求网页中的更多数据,转而对网页进行静态化,呈现于页面之中。
  
  采用javascript进行这种提取一般需要以下几步:
  1、读取网页,并匹配重定向http头获取body流,获取响应page_url。在获取响应body流的page_url后,遍历整个网页,依次匹配相应的body流,并计算出提取结果。
  2、读取提取结果,将提取结果依次放置到对应的javascript中,并计算出提取值的base64编码。
  
  3、将提取值转换为base64编码的javascript文件。根据base64编码结果,可以计算出被提取的图片链接。
  二、提取规则总体思路:从0开始,给重定向http头匹配正则表达式,计算出匹配率,通过http头约束,根据不同的匹配率分配不同的抓取规则,将匹配链接中的内容提取。例如:匹配率低于70%时,则不进行抓取。只抓取匹配率达到70%以上的规则,将该规则提取出来。
  1、正则提取匹配率http头规则::正则表达式匹配上限:500^^$一次通用问题的目标链接:/input/a#innerhtml匹配率500%*imgfor://user-agent:''*imgfor://user-agent:''*server:''*input://source=''*offset://http/input*img://user-agent:''*input://user-agent:''*text://user-agent:''*input://user-agent:''*input://inputis://(site:''*)*regexp://*sites://***。

js提取指定网站内容用php提取网页源代码用xpath解析

网站优化优采云 发表了文章 • 0 个评论 • 91 次浏览 • 2022-09-04 15:02 • 来自相关话题

  js提取指定网站内容用php提取网页源代码用xpath解析
  js提取指定网站内容
  用php提取网页源代码用xpath解析找到目标字符串
  用.eval('%(div[0].class)')会跳转到任意代码,
  fasterxml2包里面有php提取字符串的包。在不输出网页css的情况下,就可以提取字符串。也可以用专门的php提取器。
  
  php里面有这种php相关的提取器。用eval或者xpath找到你需要的那行就可以了。
  excel模板里面都是以xml文件存储的,提取这样文件中的xml,然后用php读取。要提取php中的xml文件,可以用phplr读取。
  提取视频?那就用asp脚本呗
  fasterxml2包里就有php提取,asp、python和php版本都有。
  
  activex也有的呢
  activex有php提取服务
  php可以用phplr程序正则表达式比较并查找对应字符串用activex文件属性设置runtime=nibyg.php
  强烈推荐金山搜狗输入法的导航包不用自己写php文件模板,用它自带的php提取功能就可以了如果要自己写文件提取代码,
  mysql的userdatabase就可以提取数据库,而且导出数据库配置,不过需要连接数据库;laravel不知道能不能, 查看全部

  js提取指定网站内容用php提取网页源代码用xpath解析
  js提取指定网站内容
  用php提取网页源代码用xpath解析找到目标字符串
  用.eval('%(div[0].class)')会跳转到任意代码,
  fasterxml2包里面有php提取字符串的包。在不输出网页css的情况下,就可以提取字符串。也可以用专门的php提取器。
  
  php里面有这种php相关的提取器。用eval或者xpath找到你需要的那行就可以了。
  excel模板里面都是以xml文件存储的,提取这样文件中的xml,然后用php读取。要提取php中的xml文件,可以用phplr读取。
  提取视频?那就用asp脚本呗
  fasterxml2包里就有php提取,asp、python和php版本都有。
  
  activex也有的呢
  activex有php提取服务
  php可以用phplr程序正则表达式比较并查找对应字符串用activex文件属性设置runtime=nibyg.php
  强烈推荐金山搜狗输入法的导航包不用自己写php文件模板,用它自带的php提取功能就可以了如果要自己写文件提取代码,
  mysql的userdatabase就可以提取数据库,而且导出数据库配置,不过需要连接数据库;laravel不知道能不能,

web前端工程师js提取指定网站内容抓取

网站优化优采云 发表了文章 • 0 个评论 • 91 次浏览 • 2022-08-21 06:02 • 来自相关话题

  web前端工程师js提取指定网站内容抓取
  js提取指定网站内容抓取(),抓取互联网的内容,包括静态文件和二进制文件。js提取指定网站内容可以抓取的格式不限,支持,网页,js文件,图片,网页指定区域的文本,
  javascript写法或者看下这个javascript抓取网站数据javascript抓取网站数据源码_javascript教程
  
  如果有空的话,或者确实有兴趣,可以来我这边做一个二进制文件的提取啊,
  对于我自己来说用到的就是es6:*.js*.xml*.json*.jsx
  
  js提取有很多方式,比如结构化关键字提取、文本提取、链接提取等,在目前的web前端工程师工作的角色是一个全栈开发工程师,他们的工作对于js的要求主要是三个方面,首先是兼容性,因为js还存在各种限制与兼容问题,但目前很多公司为了节省成本一般只要求实现页面的功能就可以了,这样就会对页面交互和输入输出内容有大量需求,这样就对页面内容、数据结构、排序等逻辑方面的要求提出要求。
  第二是性能问题,一个页面要同时显示很多的数据,我们可以把页面做一些拆分,也就是分区域显示,页面拆分也就成为分区域绘制等,原本很耗时的事情js可以快速完成,这样就要求页面更加简洁。第三是逻辑方面,页面中有大量的表单元素,每个表单都有类似于选择框的选择逻辑等,如果做一个模块一个模块的提取并处理所有相关表单数据,就会导致性能与一致性问题。
  对于全栈工程师来说,一个web前端工程师要根据项目对性能有硬性要求,例如几个月的工作是否在实际项目中有明显的提升等,有很多全栈开发工程师会选择使用node.js作为后端框架来实现前端框架,从而减少对前端性能的压力,而且可以加快代码在主机上的可重用性。最后结论是,前端工程师当全栈工程师比较好,因为工作量降低了对性能和一致性等方面会得到改善。 查看全部

  web前端工程师js提取指定网站内容抓取
  js提取指定网站内容抓取(),抓取互联网的内容,包括静态文件和二进制文件。js提取指定网站内容可以抓取的格式不限,支持,网页,js文件,图片,网页指定区域的文本,
  javascript写法或者看下这个javascript抓取网站数据javascript抓取网站数据源码_javascript教程
  
  如果有空的话,或者确实有兴趣,可以来我这边做一个二进制文件的提取啊,
  对于我自己来说用到的就是es6:*.js*.xml*.json*.jsx
  
  js提取有很多方式,比如结构化关键字提取、文本提取、链接提取等,在目前的web前端工程师工作的角色是一个全栈开发工程师,他们的工作对于js的要求主要是三个方面,首先是兼容性,因为js还存在各种限制与兼容问题,但目前很多公司为了节省成本一般只要求实现页面的功能就可以了,这样就会对页面交互和输入输出内容有大量需求,这样就对页面内容、数据结构、排序等逻辑方面的要求提出要求。
  第二是性能问题,一个页面要同时显示很多的数据,我们可以把页面做一些拆分,也就是分区域显示,页面拆分也就成为分区域绘制等,原本很耗时的事情js可以快速完成,这样就要求页面更加简洁。第三是逻辑方面,页面中有大量的表单元素,每个表单都有类似于选择框的选择逻辑等,如果做一个模块一个模块的提取并处理所有相关表单数据,就会导致性能与一致性问题。
  对于全栈工程师来说,一个web前端工程师要根据项目对性能有硬性要求,例如几个月的工作是否在实际项目中有明显的提升等,有很多全栈开发工程师会选择使用node.js作为后端框架来实现前端框架,从而减少对前端性能的压力,而且可以加快代码在主机上的可重用性。最后结论是,前端工程师当全栈工程师比较好,因为工作量降低了对性能和一致性等方面会得到改善。

js提取指定网站内容是什么?js怎么获取指定内容

网站优化优采云 发表了文章 • 0 个评论 • 94 次浏览 • 2022-08-20 01:01 • 来自相关话题

  js提取指定网站内容是什么?js怎么获取指定内容
  js提取指定网站内容的指定dom,获取到指定网站指定的url,获取指定网站不同指定事件的function,获取指定网站的所有段,保存到你自己存放dom的数据库中。
  mw查看内部数据库的方法:googleapisandsomeinstantgetapis:
  
  可以通过直接调用mw.list_string方法来获取相关网站的全局数据,然后用on获取你想获取的指定内容的dom节点,这个dom节点直接指向你的一级页面src指向的锚点。这样on获取到的指定字符串就是你想要获取的内容,再写入到数据库。
  js是调用的mw提供的api.list_string
  
  开发语言vs.平台,我倾向于前者,你这个问题的情景说起来挺好,有个前提你自己得知道自己研究的这个语言是一个什么样的语言,否则你很难再整个整个js领域中摸出个所以然来,另外就是不要把nodejs的我记得是叫npm这么一段代码库放在package.json中,而应该放在.vue或者.vuex这种后端平台对应的react或者express代码中,避免一个在后端服务器对应的开发环境和一个前端服务器对应的开发环境混淆。
  目测1.是这些页面还有文件夹2.是网页本身代码获取一页详细资料4.肯定有一个node服务器
  网页源码中list_string字段,前面有个url图标,进入页面时在nodewindow窗口下打开命令npminstall-gjquery即可。 查看全部

  js提取指定网站内容是什么?js怎么获取指定内容
  js提取指定网站内容的指定dom,获取到指定网站指定的url,获取指定网站不同指定事件的function,获取指定网站的所有段,保存到你自己存放dom的数据库中。
  mw查看内部数据库的方法:googleapisandsomeinstantgetapis:
  
  可以通过直接调用mw.list_string方法来获取相关网站的全局数据,然后用on获取你想获取的指定内容的dom节点,这个dom节点直接指向你的一级页面src指向的锚点。这样on获取到的指定字符串就是你想要获取的内容,再写入到数据库。
  js是调用的mw提供的api.list_string
  
  开发语言vs.平台,我倾向于前者,你这个问题的情景说起来挺好,有个前提你自己得知道自己研究的这个语言是一个什么样的语言,否则你很难再整个整个js领域中摸出个所以然来,另外就是不要把nodejs的我记得是叫npm这么一段代码库放在package.json中,而应该放在.vue或者.vuex这种后端平台对应的react或者express代码中,避免一个在后端服务器对应的开发环境和一个前端服务器对应的开发环境混淆。
  目测1.是这些页面还有文件夹2.是网页本身代码获取一页详细资料4.肯定有一个node服务器
  网页源码中list_string字段,前面有个url图标,进入页面时在nodewindow窗口下打开命令npminstall-gjquery即可。

js提取指定网站内容的页面进行爬取简单易用

网站优化优采云 发表了文章 • 0 个评论 • 96 次浏览 • 2022-08-18 22:06 • 来自相关话题

  js提取指定网站内容的页面进行爬取简单易用
  js提取指定网站内容的页面进行爬取,抓取的数据直接保存在网站数据库中,简单易用。下面我们就通过一个实例来分析js提取json数据。
  好像有些网站直接返回html,看那个语言能写了。
  
  js提取json数据是一个很蛋疼的事情。json提取出来放到数据库里是一堆没有意义的东西。所以干脆不应该给数据提取出来。而是好好想想如何设计一个简单、高效的检索结构。另外一个比较好的办法就是用比如setdata做一些映射操作,另外这些操作采用workflow来操作很合理,另外可以完全在本地操作。
  jsoncurl这个库有js代码,
  简单来说,可以借助一些工具来提取,然后转换成json。我比较喜欢torbir这个库提供的workflow。
  
  我觉得楼上写的很详细了,我来说一下我遇到的问题,然后我的方法和结果w3cschool:js提取xxx以xxx作为key-value就可以转成json了torbir:中文乱码、区分小写-->advent+key-valueonly关键点:想象一下要解析的url有什么样的组成,有哪些字段,然后一个一个进行处理,然后一点一点output到数据库。
  requests+requestslib/requests
  这是一个快速开发爬虫的一个很不错的库github-eternalfool/cuttera:apythonthatlookssoimportantincuttingjson. 查看全部

  js提取指定网站内容的页面进行爬取简单易用
  js提取指定网站内容的页面进行爬取,抓取的数据直接保存在网站数据库中,简单易用。下面我们就通过一个实例来分析js提取json数据。
  好像有些网站直接返回html,看那个语言能写了。
  
  js提取json数据是一个很蛋疼的事情。json提取出来放到数据库里是一堆没有意义的东西。所以干脆不应该给数据提取出来。而是好好想想如何设计一个简单、高效的检索结构。另外一个比较好的办法就是用比如setdata做一些映射操作,另外这些操作采用workflow来操作很合理,另外可以完全在本地操作。
  jsoncurl这个库有js代码,
  简单来说,可以借助一些工具来提取,然后转换成json。我比较喜欢torbir这个库提供的workflow。
  
  我觉得楼上写的很详细了,我来说一下我遇到的问题,然后我的方法和结果w3cschool:js提取xxx以xxx作为key-value就可以转成json了torbir:中文乱码、区分小写-->advent+key-valueonly关键点:想象一下要解析的url有什么样的组成,有哪些字段,然后一个一个进行处理,然后一点一点output到数据库。
  requests+requestslib/requests
  这是一个快速开发爬虫的一个很不错的库github-eternalfool/cuttera:apythonthatlookssoimportantincuttingjson.

js提取指定网站内容(表格、图片等)是什么?

网站优化优采云 发表了文章 • 0 个评论 • 78 次浏览 • 2022-08-18 19:03 • 来自相关话题

  js提取指定网站内容(表格、图片等)是什么?
  js提取指定网站内容(表格、图片等)html,xml转换js,css都可以,适合已有模板情况下,节省网站构建。和jquery,bootstrap搭配的更和谐。
  看你只提取哪一个类别吧?是图片?是网页文本?要做效果的话,现在还有一些可以和js搭配使用的方法,但是基本上都是“模块化”的,有限的js方面调整,写哪个页面就改哪个页面里面的内容而已,可以节省大量的工作量,但是有的就要修改很多次。
  
  网站页面分三类:html模板、js和css文件。如果只是提取首页的html文件就好办了。关键是写好各个部分的模板。组装方面就很难做了,需要熟悉jquery或者google的sass。不可能把所有东西都封装成js,结构上和设计上的差异还是有的。在特定的场景下需要考虑的地方比较多。
  高版本的浏览器可以设置sourcemode属性的。还有就是,你大概也不会特意设置加载模板文件的。
  高版本的浏览器都是不支持这个东西的。
  
  对方的js肯定和我一样是拿脚本写的
  如果版本低,估计需要重写js部分。版本高的版本可以写脚本。
  我也是设计师,拿我自己的经验说一下:不建议使用js提取数据可能要拼接,很麻烦。直接改html文件内容便可,可以简化js部分。
  把页面拆分,各个模块改来改去就可以了,尽量用前后端控制,如果页面不大, 查看全部

  js提取指定网站内容(表格、图片等)是什么?
  js提取指定网站内容(表格、图片等)html,xml转换js,css都可以,适合已有模板情况下,节省网站构建。和jquery,bootstrap搭配的更和谐。
  看你只提取哪一个类别吧?是图片?是网页文本?要做效果的话,现在还有一些可以和js搭配使用的方法,但是基本上都是“模块化”的,有限的js方面调整,写哪个页面就改哪个页面里面的内容而已,可以节省大量的工作量,但是有的就要修改很多次。
  
  网站页面分三类:html模板、js和css文件。如果只是提取首页的html文件就好办了。关键是写好各个部分的模板。组装方面就很难做了,需要熟悉jquery或者google的sass。不可能把所有东西都封装成js,结构上和设计上的差异还是有的。在特定的场景下需要考虑的地方比较多。
  高版本的浏览器可以设置sourcemode属性的。还有就是,你大概也不会特意设置加载模板文件的。
  高版本的浏览器都是不支持这个东西的。
  
  对方的js肯定和我一样是拿脚本写的
  如果版本低,估计需要重写js部分。版本高的版本可以写脚本。
  我也是设计师,拿我自己的经验说一下:不建议使用js提取数据可能要拼接,很麻烦。直接改html文件内容便可,可以简化js部分。
  把页面拆分,各个模块改来改去就可以了,尽量用前后端控制,如果页面不大,

js提取指定网站内容,包括图片、数据、视频等

网站优化优采云 发表了文章 • 0 个评论 • 225 次浏览 • 2022-08-07 16:00 • 来自相关话题

  js提取指定网站内容,包括图片、数据、视频等
  js提取指定网站内容,包括图片、数据、视频等,可以把正文文本提取出来,把正文文本替换成网址,方便加入到图片等数据中。视频音频数据提取比较麻烦。markdown编辑器很少,建议用notepad++,sublimetext2,vim等,免费软件。yandex.yml,yandex.markdown是国内开发的,比较简单,基本html和flash页面都可以替换,用户体验较好。使用chrome打开网站,安装webpack,打开console,输入你需要的参数。
  提取微信文章里的图片?
  可以用markdown编辑器,把文章内容提取出来,
  
  youtube的articlemanager,
  yahooprime的图片提取工具javascriptwebglstudio可以提取微信上所有的图片:
  更快捷的方法:yahooprime自带sourcearticle功能,
  
  最好是用浏览器插件来解决,安装对应的浏览器扩展程序,然后保存,再选择解压到想要的目录。mac上:chrome浏览器的「扩展程序」页面,有些mac上已经有对应的扩展程序;firefox的扩展程序网站,有些有,
  这个很有用的owasp的html5工具,推荐使用gochrome的,
  如果是从html转换成html5的,比如你是要从html的内容转换成js、css、sass等是应该可以的,html5工具网站很多比如:html5icons(javascript/cssicons)如果需要从html转换成css可以用jemarketforever再说也可以上bootstrap官网看看的css能做些什么:,你总是可以找到的对吧,就是看你的技术能力了。
  html5exchange推荐一个qa:exchangevs.quickpatch支持的工具就更多了。不同工具实现功能差别蛮大的,必须具体需求才能区分哪个好哪个不好。 查看全部

  js提取指定网站内容,包括图片、数据、视频等
  js提取指定网站内容,包括图片、数据、视频等,可以把正文文本提取出来,把正文文本替换成网址,方便加入到图片等数据中。视频音频数据提取比较麻烦。markdown编辑器很少,建议用notepad++,sublimetext2,vim等,免费软件。yandex.yml,yandex.markdown是国内开发的,比较简单,基本html和flash页面都可以替换,用户体验较好。使用chrome打开网站,安装webpack,打开console,输入你需要的参数。
  提取微信文章里的图片?
  可以用markdown编辑器,把文章内容提取出来,
  
  youtube的articlemanager,
  yahooprime的图片提取工具javascriptwebglstudio可以提取微信上所有的图片:
  更快捷的方法:yahooprime自带sourcearticle功能,
  
  最好是用浏览器插件来解决,安装对应的浏览器扩展程序,然后保存,再选择解压到想要的目录。mac上:chrome浏览器的「扩展程序」页面,有些mac上已经有对应的扩展程序;firefox的扩展程序网站,有些有,
  这个很有用的owasp的html5工具,推荐使用gochrome的,
  如果是从html转换成html5的,比如你是要从html的内容转换成js、css、sass等是应该可以的,html5工具网站很多比如:html5icons(javascript/cssicons)如果需要从html转换成css可以用jemarketforever再说也可以上bootstrap官网看看的css能做些什么:,你总是可以找到的对吧,就是看你的技术能力了。
  html5exchange推荐一个qa:exchangevs.quickpatch支持的工具就更多了。不同工具实现功能差别蛮大的,必须具体需求才能区分哪个好哪个不好。

js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api

网站优化优采云 发表了文章 • 0 个评论 • 93 次浏览 • 2022-07-26 20:08 • 来自相关话题

  js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api
  js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api去爬虫别人提取网站内容一样,这个web视频是在chrome的开发者工具里,用的是抓包方式提取网页内容,会发现抓包的过程中是加密的。一、加密方式:一种简单粗暴的方式是,直接把网页内容的域名解析出来然后把加密的html的内容生成js的代码供浏览器解析,如下图,这种方式适合一些必须通过https通道进行交互的场景。
  
  另一种方式是,利用反向代理,把普通的代理服务器伪装成浏览器进行访问,目前百度的代理加速还是不错的,做成一个域名绑定的解析js代码,利用https通道进行跨越代理访问,或者做一个反向代理服务器绑定一个静态站点,用这个静态站点做代理访问的代理服务器伪装成浏览器来解析加密html,如下图,这种方式只适合解析带有指定链接的文章。
  
  二、源码格式:对于没有url结构的文章,可以考虑将网页源码生成url结构,对一些内容较多的文章可以根据网页包含的关键词提取关键信息,如下图,可以提取“婚纱摄影“所对应的url结构。不同层级的站点(网站),网页结构都可以做一些定制,比如生成出树状的结构,非结构化文件提取更加容易,不同页面能够在最短的时间内提取出大部分信息。
  比如知乎的首页,知乎上包含了很多话题,可以将这些结构化的东西抽象成树状的组织结构,或者做成文件夹的方式来生成树状结构,方便提取,抽象方式如下图,抽象的树状结构如下图,抽象树状结构这种方式适合抽象较少的文件的文章内容,比如歌曲名称和歌曲存档等等。当然可以直接定制一个所有的页面的定制过程,构建api库,来抽象一些url结构,抽象一些关键词,但是代码量比较大。---欢迎大家关注我的公众号:【程序人生】。这里有和大家分享一些高效学习的方法和干货。 查看全部

  js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api
  js提取指定网站内容的代码,类似于爬虫,就像你不能用你提取代码的api去爬虫别人提取网站内容一样,这个web视频是在chrome的开发者工具里,用的是抓包方式提取网页内容,会发现抓包的过程中是加密的。一、加密方式:一种简单粗暴的方式是,直接把网页内容的域名解析出来然后把加密的html的内容生成js的代码供浏览器解析,如下图,这种方式适合一些必须通过https通道进行交互的场景。
  
  另一种方式是,利用反向代理,把普通的代理服务器伪装成浏览器进行访问,目前百度的代理加速还是不错的,做成一个域名绑定的解析js代码,利用https通道进行跨越代理访问,或者做一个反向代理服务器绑定一个静态站点,用这个静态站点做代理访问的代理服务器伪装成浏览器来解析加密html,如下图,这种方式只适合解析带有指定链接的文章。
  
  二、源码格式:对于没有url结构的文章,可以考虑将网页源码生成url结构,对一些内容较多的文章可以根据网页包含的关键词提取关键信息,如下图,可以提取“婚纱摄影“所对应的url结构。不同层级的站点(网站),网页结构都可以做一些定制,比如生成出树状的结构,非结构化文件提取更加容易,不同页面能够在最短的时间内提取出大部分信息。
  比如知乎的首页,知乎上包含了很多话题,可以将这些结构化的东西抽象成树状的组织结构,或者做成文件夹的方式来生成树状结构,方便提取,抽象方式如下图,抽象的树状结构如下图,抽象树状结构这种方式适合抽象较少的文件的文章内容,比如歌曲名称和歌曲存档等等。当然可以直接定制一个所有的页面的定制过程,构建api库,来抽象一些url结构,抽象一些关键词,但是代码量比较大。---欢迎大家关注我的公众号:【程序人生】。这里有和大家分享一些高效学习的方法和干货。

js提取指定网站内容提取robots.txt文件可实现更多功能

网站优化优采云 发表了文章 • 0 个评论 • 96 次浏览 • 2022-07-22 07:03 • 来自相关话题

  js提取指定网站内容提取robots.txt文件可实现更多功能
  
  js提取指定网站内容,wordpress提取指定网站内容相比之下,wordpress提取robots.txt文件可实现更多的功能。同时还可以根据网站类型,提取性能更佳。网站提取网站内容基本分两种。一种是提取主题代码。一种是提取控制器代码。二者区别如下:1.提取控制器主要原理:在控制器后面生成一个.img标签,上面有网站首页的url,然后写入.html格式的文件中。
  
  2.提取主题提取主题,比较常见的方法就是使用网站模板提取首页:在本地生成这个主题的.html文件,上传到last.php到last.php中。如下:这样,就生成了主题的html页面。这样在网站后台,就可以提取到首页的内容。当然,上图中使用了反向代理,如果不需要代理,或代理地址为空,则无法提取。另外也可以使用网站的二级域名对应的主题二级域名对应的主题为。如下:我这里使用二级域名查询,也可以查询一级域名对应的主题页面。
  第一步,首先,在你的wordpress网站,运行一个插件,基于wordpress新增一个host,这个主机名,如,安装这个插件,手动设置,并记录。第二步,运行第一步实现的host后,将baiduspider设置路径指向:../wordpress/wp-content.php第三步,将测试获取的内容导出到excel第四步,在你测试的网站下,直接操作,就可以读取数据了。例如,你测试了test的文章,那么在test这个主题的host中,就可以查到主题的源代码文件。 查看全部

  js提取指定网站内容提取robots.txt文件可实现更多功能
  
  js提取指定网站内容,wordpress提取指定网站内容相比之下,wordpress提取robots.txt文件可实现更多的功能。同时还可以根据网站类型,提取性能更佳。网站提取网站内容基本分两种。一种是提取主题代码。一种是提取控制器代码。二者区别如下:1.提取控制器主要原理:在控制器后面生成一个.img标签,上面有网站首页的url,然后写入.html格式的文件中。
  
  2.提取主题提取主题,比较常见的方法就是使用网站模板提取首页:在本地生成这个主题的.html文件,上传到last.php到last.php中。如下:这样,就生成了主题的html页面。这样在网站后台,就可以提取到首页的内容。当然,上图中使用了反向代理,如果不需要代理,或代理地址为空,则无法提取。另外也可以使用网站的二级域名对应的主题二级域名对应的主题为。如下:我这里使用二级域名查询,也可以查询一级域名对应的主题页面。
  第一步,首先,在你的wordpress网站,运行一个插件,基于wordpress新增一个host,这个主机名,如,安装这个插件,手动设置,并记录。第二步,运行第一步实现的host后,将baiduspider设置路径指向:../wordpress/wp-content.php第三步,将测试获取的内容导出到excel第四步,在你测试的网站下,直接操作,就可以读取数据了。例如,你测试了test的文章,那么在test这个主题的host中,就可以查到主题的源代码文件。

js提取指定网站内容并保存至数据库提取内容内容

网站优化优采云 发表了文章 • 0 个评论 • 83 次浏览 • 2022-07-18 07:05 • 来自相关话题

  js提取指定网站内容并保存至数据库提取内容内容
  js提取指定网站内容并保存至数据库提取网站内容并存入数据库
  1.用一些好用的web工具,
  看到一篇文章,觉得写的很好,
  
  重点:javascript
  可以使用一些浏览器脚本
  ssr这种东西,都看不到自己的服务器端实现的方法,岂不就是拿无知开涮,
  不看你网站文档,
  
  ajax这种东西都看不到自己的服务器端实现的方法,岂不就是拿无知开涮,拿没开发过的东西开涮?web前端培训这么火,很多没写过网站的都在培训网站了,谁能想到这种东西竟然也有培训?自己没把握好,来这问,不如问专业的前端程序员。
  单页应用,三层form,点击通过表单等通道触发处理。
  还是你不懂计算机,没有扎实的基础,写不了一个稳定的web应用,你就算搞出来也是扯淡。
  经常看到web前端,所谓phpweb前端开发,就是用php写一个页面,web后端有java,go等,再写一套自己的后端代码去测试上线。另外那句话用在你身上没问题,但是你应该去问java,php,go等前端开发的人,他们应该比你懂的多。至于你应该从哪学习,你应该自己去看看怎么去搞web前端才不扯淡。 查看全部

  js提取指定网站内容并保存至数据库提取内容内容
  js提取指定网站内容并保存至数据库提取网站内容并存入数据库
  1.用一些好用的web工具,
  看到一篇文章,觉得写的很好,
  
  重点:javascript
  可以使用一些浏览器脚本
  ssr这种东西,都看不到自己的服务器端实现的方法,岂不就是拿无知开涮,
  不看你网站文档,
  
  ajax这种东西都看不到自己的服务器端实现的方法,岂不就是拿无知开涮,拿没开发过的东西开涮?web前端培训这么火,很多没写过网站的都在培训网站了,谁能想到这种东西竟然也有培训?自己没把握好,来这问,不如问专业的前端程序员。
  单页应用,三层form,点击通过表单等通道触发处理。
  还是你不懂计算机,没有扎实的基础,写不了一个稳定的web应用,你就算搞出来也是扯淡。
  经常看到web前端,所谓phpweb前端开发,就是用php写一个页面,web后端有java,go等,再写一套自己的后端代码去测试上线。另外那句话用在你身上没问题,但是你应该去问java,php,go等前端开发的人,他们应该比你懂的多。至于你应该从哪学习,你应该自己去看看怎么去搞web前端才不扯淡。

js提取指定网站内容是怎么做的?js怎么提取

网站优化优采云 发表了文章 • 0 个评论 • 210 次浏览 • 2022-07-16 07:03 • 来自相关话题

  js提取指定网站内容是怎么做的?js怎么提取
  js提取指定网站内容一直是我想实现的,但是只是执行js写的。其实也可以用http协议下发一个指定链接,然后js进行获取,但是这样做对于大多数网站来说要在需要获取js的网站连接域名有域名才可以。后来我用tiobe排名的时候,发现chrome非常难找,没有查询完全页的cannonic浏览器,是没有对应浏览器。
  
  于是考虑js爬虫+requests+selenium+shell就可以全自动的抓取。为了获取一个html页面,首先需要抓取一个html页面,然后要将其下载下来。通过百度找到这个页面,进行如下操作:1.单击页面上方“访问页面”,获取index.html并解析成为一个xml2.打开浏览器的开发者工具,在地址栏中打开xml文件,进行解析.3.在executable内外抓取相应的页面,并将抓取出来的executable复制到浏览器地址栏,获取页面内容文件。
  4.将获取好的js文件添加到浏览器中,正常页面会在下一个文件中。整个操作过程最长两分钟左右。然后获取的html将直接存储到js文件中。后来发现js文件打开比较慢,我们还需要使用正则表达式才能找到相应的页面,以下代码就是进行正则表达式匹配,来得到页面。1.打开页面,鼠标右键选择检查,,然后选择以页面中的元素为中心(包括标题,文字,img,footer,iframe等)点击菜单:network->pages,右键->匹配正则,命名搜索出来的文件内容中匹配页面中任意一个条件为字符串的文件,也可以自己选择executable下复制的文件夹名。
  
  一般情况下页面都有几十上百个,加上文件名的条件,也有上千条左右。2.找到和我们想要匹配出来文件的文件名,再放进pages中(以页面中的index.html为例)functiongetheaderpagescontext(pagescontext){for(letline:pagescontext){if(line.startswith("\n")&&line.startswith("\n")){returnnull;}}return0;}正则匹配案例3.如果拿到pagesoftend中的内容:我们只需要通过正则表达式找到页面中的xhtml文件后缀,然后匹配相应的文件,保存相应的文件,再将此文件放到浏览器的开发者工具的文件夹目录下,就能获取该网页的更多内容。
  将找到的xhtml内容内容保存到.exe文件中以后,我们可以修改后缀名。修改时有个原则,即每次都需要知道这个网页最后标签名的后缀。如果代码写得足够优美的话,代码可以非常简洁,但是为了快速,这是必须。重新思考下代码,代码如下:.exe-p-i-f.unkeys.submodule.index.htmlindex.html其实代码就是重复getheaderpagescontext(pagescont。 查看全部

  js提取指定网站内容是怎么做的?js怎么提取
  js提取指定网站内容一直是我想实现的,但是只是执行js写的。其实也可以用http协议下发一个指定链接,然后js进行获取,但是这样做对于大多数网站来说要在需要获取js的网站连接域名有域名才可以。后来我用tiobe排名的时候,发现chrome非常难找,没有查询完全页的cannonic浏览器,是没有对应浏览器。
  
  于是考虑js爬虫+requests+selenium+shell就可以全自动的抓取。为了获取一个html页面,首先需要抓取一个html页面,然后要将其下载下来。通过百度找到这个页面,进行如下操作:1.单击页面上方“访问页面”,获取index.html并解析成为一个xml2.打开浏览器的开发者工具,在地址栏中打开xml文件,进行解析.3.在executable内外抓取相应的页面,并将抓取出来的executable复制到浏览器地址栏,获取页面内容文件。
  4.将获取好的js文件添加到浏览器中,正常页面会在下一个文件中。整个操作过程最长两分钟左右。然后获取的html将直接存储到js文件中。后来发现js文件打开比较慢,我们还需要使用正则表达式才能找到相应的页面,以下代码就是进行正则表达式匹配,来得到页面。1.打开页面,鼠标右键选择检查,,然后选择以页面中的元素为中心(包括标题,文字,img,footer,iframe等)点击菜单:network->pages,右键->匹配正则,命名搜索出来的文件内容中匹配页面中任意一个条件为字符串的文件,也可以自己选择executable下复制的文件夹名。
  
  一般情况下页面都有几十上百个,加上文件名的条件,也有上千条左右。2.找到和我们想要匹配出来文件的文件名,再放进pages中(以页面中的index.html为例)functiongetheaderpagescontext(pagescontext){for(letline:pagescontext){if(line.startswith("\n")&&line.startswith("\n")){returnnull;}}return0;}正则匹配案例3.如果拿到pagesoftend中的内容:我们只需要通过正则表达式找到页面中的xhtml文件后缀,然后匹配相应的文件,保存相应的文件,再将此文件放到浏览器的开发者工具的文件夹目录下,就能获取该网页的更多内容。
  将找到的xhtml内容内容保存到.exe文件中以后,我们可以修改后缀名。修改时有个原则,即每次都需要知道这个网页最后标签名的后缀。如果代码写得足够优美的话,代码可以非常简洁,但是为了快速,这是必须。重新思考下代码,代码如下:.exe-p-i-f.unkeys.submodule.index.htmlindex.html其实代码就是重复getheaderpagescontext(pagescont。

js提取指定网站内容-上海怡诺唐咨询公司

网站优化优采云 发表了文章 • 0 个评论 • 80 次浏览 • 2022-07-09 03:00 • 来自相关话题

  js提取指定网站内容-上海怡诺唐咨询公司
  js提取指定网站内容然后拼接成一个文本的,webpack有一个babel的插件可以提取,jquery也可以提取。用xml提取文本类似,但xml只能一份一份转化,具体对应的格式也有提取。
  所有的东西都可以按我的要求提取出来?我要的是这个网站提取出来,后缀多一个zhihu提取出来。
  
  一般这种情况都是直接拼接成字符串了,比如这个网站。
  有可能是用xml库解析js生成的body之后,js直接就直接component成了一个固定的view/state了吧。可以用xml.loader把js组件转成xml序列格式再转成json(大部分json.parser都是这么干的)。
  @parents关注了这个问题。感觉是obejct数据解析出来的,
  
  用的是xml.parser(看到了第一名的eloquentjs,但是我想了想可能在写法上差了一点)。可以传入值自己配置xmlplugin的类型参数。read:body-{value:string,source:'xml'}document:text-source//don'tchangecontent-type,最好不要试图改写json';em'来解析。
  既然你都打算写解析了为什么还要有这种问题?
  看了某位的回答,我觉得上面有个答案有问题。给你写个例子。你在xml里面输入一串包含"weixin"的数据,点“gitcommit",然后把xml发送给服务器。服务器会处理生成json的数据再解析成"weixin"为你提交的"weixin"这样。但是你打算说的是,在js中用xml.parser读xml数据生成json再发送到服务器,请问有可能生成json再转换成js么?可能是兼容性的问题,但是无论哪种,你的做法毫无必要。我的方法就是在js里面处理json,将它再封装成xml。最终的效果就是把xml变成json。 查看全部

  js提取指定网站内容-上海怡诺唐咨询公司
  js提取指定网站内容然后拼接成一个文本的,webpack有一个babel的插件可以提取,jquery也可以提取。用xml提取文本类似,但xml只能一份一份转化,具体对应的格式也有提取。
  所有的东西都可以按我的要求提取出来?我要的是这个网站提取出来,后缀多一个zhihu提取出来。
  
  一般这种情况都是直接拼接成字符串了,比如这个网站。
  有可能是用xml库解析js生成的body之后,js直接就直接component成了一个固定的view/state了吧。可以用xml.loader把js组件转成xml序列格式再转成json(大部分json.parser都是这么干的)。
  @parents关注了这个问题。感觉是obejct数据解析出来的,
  
  用的是xml.parser(看到了第一名的eloquentjs,但是我想了想可能在写法上差了一点)。可以传入值自己配置xmlplugin的类型参数。read:body-{value:string,source:'xml'}document:text-source//don'tchangecontent-type,最好不要试图改写json';em'来解析。
  既然你都打算写解析了为什么还要有这种问题?
  看了某位的回答,我觉得上面有个答案有问题。给你写个例子。你在xml里面输入一串包含"weixin"的数据,点“gitcommit",然后把xml发送给服务器。服务器会处理生成json的数据再解析成"weixin"为你提交的"weixin"这样。但是你打算说的是,在js中用xml.parser读xml数据生成json再发送到服务器,请问有可能生成json再转换成js么?可能是兼容性的问题,但是无论哪种,你的做法毫无必要。我的方法就是在js里面处理json,将它再封装成xml。最终的效果就是把xml变成json。

如何用 Node.js 和 Elasticsearch 构建搜索引擎

网站优化优采云 发表了文章 • 0 个评论 • 84 次浏览 • 2022-07-02 19:05 • 来自相关话题

  如何用 Node.js 和 Elasticsearch 构建搜索引擎
  数据导入
  在本教程中,我将使用 1000 篇学术论文里的内容,这些内容是根据随机算法逐一生成的,并以 JSON 格式提供,其中的数据格式如下所示:
  JSON 格式中的每个字段如字面意思,无需多余解释,但值得注意的是:由于包含随机生成的文章的全部的内容(大概有100~200个段落),所以并未展示。
  虽然 Elasticsearch 提供了索引(indexing),更新(updating)、删除(deleting)单个数据的方法,但我们采用批量(bulk)接口导入数据,因为批量接口在大型数据集上执行操作的效率更高。
  这里,我们调用函数bulkIndex建立索引,并传入 3 个参数,分别是:索引名 library,类型名library,JSON 数据格式变量 articles。bulkIndex函数自身则通过调用esClient对象的bulk接口实现,bulk 方法包含一个body属性的对象参数,并且每个body属性值是一个包含 2 种操作实体的数组对象。第一个实体是 JSON 格式的操作类型对象,该对象中的index属性决定了操作的类型(本例子是文件索引)、索引名、文件ID。第二个实体则是文件对象本身。
  注意,后续可采用同样的方式,为其他类型文件(如书籍或者报告)添加索引。我们还可以有选择的每个文件分配一个唯一的ID,如果不体统唯一的ID,Elasticsearch 将主动为每个文件分配一个随机的唯一ID。
  假设你已经从代码库中下载了 Elasticsearch 项目代码,在项目根目录下执行如下命令,即可将数据导入至Elasticsearch中:
  检查数据的索引是否准确
  Elasticsearch 最大的特性是接近实时检索,这意味着,一旦文档索引建立完成,1 秒内就可被检索(见这里)。索引一旦建立完成,则可通过运行 indice.js 检查索引信息的准确性(源码链接):
  client 中的cat 对象方法提供当前运行实例的各种信息。其中的 indices 方法列出所有的索引信息,包括每个索引的健康状态、以及占用的磁盘大小。 而其中的 v 选项为 cat方法新增头部响应。
  当运行上面代码段,您会发现,集群的健康状态被不同的颜色标示。其中,红色表示为正常运行的有问题集群;黄色表示集群可运行,但存在告警;绿色表示集群正常运行。在本地运行上面的代码段,您极有可能(取决于您的配置)看到集群的健康状态颜色是黄色,这是因为默认的集群设置包含 5 个节点,但本地运行只有 1 个实例正常运行。鉴于本教程的目的仅局限于 Elasticsearch 指导学习,黄色即可。但在线上环境中,你必须确保集群的健康状态颜色是绿色的。
  动态和自定义映射
  如前所述, Elasticsearch 无模式(schema-free),这意味着,在数据导入之前,您无需定义数据的结构(类似于SQL数据库需要预先定义表结构),Elasticsearch 会主动检测。尽管 Elasticsearch 被定义为无模式,但数据结构上仍有些限制。
  Elasticsearch 以映射的方式引用数据结构。当数据索引建立完成后,如果映射不存在,Elasticsearch 会依次检索 JSON 数据的每个字段,然后基于被字段的类型(type)自动生成映射(mapping)。如果存在该字段的映射,则会确保按照同样的映射规则新增数据。否则直接报错。
  比如:如果{"key1": 12}已经存在,Elasticsearch 自动将字段 key1 映射为长整型。现在如果你尝试通过{"key1": "value1", "key2": "value2"} 检索, 则会直接报错,因为系统预期字段 key1 为长整型。同时,如果通过{"key1": 13, "key2": "value2"} 检索则不会报错,并为字段 key2 新增 string 类型。
  映射不能超出文本的范围,大都数情况下,系统自动生成的映射都可正常运行。
  构建搜索引擎
  一旦完成数据索引,我们就可以开始实现搜索引擎。Elasticsearch提供了一个直观的基于JSON的全搜索查询的结构-Query DSL,定义查询。有许多有用的搜索查询类型,但是在这篇文章中,我们将只看到几个通用的类型。关于Query DSL的完整文章可以在这里看到。
  请记住,我提供了每个展示例子的源码的连接。设置完你的环境和索引测试数据后,你可以下载源码,然后运行在你的机器上运行任何例子。可以通过命令行运行节点filename.js。
  
  返回一个或多个索引的所有记录
  为了执行我们的搜索,我们将使用客户端提供的多种搜索方法。最简单的查询是match_all,它可以返回一个或多个索引的所有的记录。下面的例子显示了我们怎么样获取在一个索引中获取所有存储的记录(源码).
  主要的搜索查询包含在Query对象中。就像我们接下来看到的那样,我们可以添加不同的搜索查询类型到这个对象。我们可以为每一个Query添加一个查询类型的关键字(如match_all),让这个Query成为一个包含搜索选项的对象。由于我们想返回索引的所有记录,所以在这个例子中没有查询选项。
  除了Query对象,搜索体中可以包含其他选项的属性,如size和from。size属性决定了返回记录的数量。如果这个值不存在,默认返回10个记录。from属性决定了返回记录的起始索引,这对分页有用。
  理解查询API的返回结果
  如果你打印搜索API返回结果(上面例子的结果)日志。由于它包含了很多信息,刚开始看起来无所适从。
  在最高级别日志输出里,返回结果中含有took属性,该属性值表示查找结果所用的毫秒数,timed_out只有在最大允许时间内没有找到结果时为true,_shards是不同节点的状态的信息(如果部署的是节点集群),hits是查询结果。
  hits的属性值是一个含有下列属性的对象:
  这十分复杂,但是好消息是一旦你实现了一个提取结果的方法,不管你的搜索查询结果时什么,你都可以使用相同的格式获取结果。
  还需要注意的是Elasticsearch有一个好处是它自动地给每一个匹配记录分配分数,这个分数用来量化文件的关联性,返回结果的顺序默认的按钮分数倒排。在例子中我们使用match_all取回了所有的记录,分数是没有意义的,所有的分数都被计算为1.0。
  匹配含指定字段值的文档
  现在我们看几个更加有趣的例子. 我们可以通过使用 match 关键字查询文档是否与指定的字段值匹配。一个最简单的包含 match 关键字的检索主体代码如下所示:
  如上文所述, 首先通过为查询对象新增一个条目,并指定检索类型,上面示例给的是 match 。然后再检索类型对象里面,申明待检索的文档对象,本例是 title 文档对象。然后再文档对象里面,提供相关检索数据,和 query 属性。我希望你测试过上述示例之后,惊讶于 Elasticsearch 的检索效率。
  上述示例执行成功后,将返回title(标题)字段与任一 query 属性词匹配的所有文档信息。同时还可以参考如下示例,为查询对象附加最小匹配数量条件:
  与该查询匹配的文档 title(标题)字段至少包含上诉指定的 3 个关键词。如果查询关键词少于 3个,那么匹配文档的 title(标题)字段必须包含所有的查询词。Elasticsearch 的另一个有用的功能是fuzziness(模糊匹配).这对于用户输入错误的查询词将非常有用,因为fuzzy(模糊匹配)将发现拼写错误并给出最接近词供选择。对于字符串类型,每个关键字的模糊匹配值是根据算法Levenshtein distance算出的最大允许值。fuzziness(模糊匹配)示例如下所示:
  多个字段搜索
  如果你想在多个字段中搜索,可以使用multi_match搜索类型。除了Query对象中的fields属性外,它同match有点类似。fields属性是需要搜索的字段的集合。这里我们将在title,authors.firstname, 和authors.lastname字段中搜索。
  multi_match查询支持其他搜索属性,如minimum_should_match和fuzziness。Elasticsearch支持使用通配符(如*)匹配字段,那么我们可以使用['title', 'authors.*name']把上面的例子变得更短些。
  匹配一个完整的句子
  Elasticsearch也支持精确的匹配一个输入的句子,而不是在单词级别。这个查询是在普通的match查询上扩展而来,叫做match_phrase。下面是一个match_phrase的例子
  
  联合多个查询
  到目前为止,在例子中我们每次请求只使用了单个查询。然而Elasticsearch允许你联合多个查询。最常用的复合查询是bool,bool查询接受4种关键类型must,should,must_not, 和filter.像它们的名字表示的那样,在查询结果的数据里必须匹配must里的查询,必须不匹配must_not里的查询,如果哪个数据匹配should里的查询,它就会获得高分。每一个提到的元素可以使用查询数组格式接受多个搜索查询。
  下面,我们使用bool查询及一个新的叫做query_string的查询类型。它允许你使用AND或OR写一些比较高级的查询。另外,我们使用了range查询,它可以让我们通过给定的范围的方式去限制一个字段。
  在上面的例子中,查询返回的数据,作者的名包含term1或它们的姓包含term2,并且它们的title含有term3,而且它们不在2011,2012或2013年出版的,还有在body字段里含有给定句子数据将获得高分,并被排列到结果的前面(由于在should从句中的match查询)。
  过滤,聚合,和建议
  除了它先进的搜索功能外,Elasticsearch还提供了其他的功能。接下来,我们再看看其他三个比较常用的功能。
  过滤
  也许,你经常想使用特定的条件凝缩查询结果。Elasticsearch通过filters提供了这样的功能。在我们的文章数据里,假设你的查询返回了几个文章,这些文章是你选择的在5个具体年份发布的文章。你可以简单的从搜索结果中过滤出那些不匹配条件的数据,而不改变查询结果的顺序。
  在bool查询的must从句中,过滤和相同查询之间的不同之处在于,过滤不会影响搜索分数,而must查询会。当查询结果返回并且用户使用给定的条件过滤时,他们不想改变结果的顺序,相反地,他们只想从结果中移除不相关的数据。过滤与搜索的格式一样,但在通常情况下,他们在有明确值的字段上定义,而不是文本字符串上。Elasticsearch推荐通过bool复合查询的filter从句添加过滤。
  继续看上面的例子,假设我们想把搜索结果限制在在2011到2015年之间发布的文章里。这样做,我们只需要在一般搜索查询的filter部分添加range查询。这将会从结果中移除那些不匹配的数据。下面是一个过滤查询的例子
  聚合
  聚合框架会基于一次搜索查询,提供各种聚合数据和统计信息。两个主要的聚合类型是度量和分块, 度量聚合会对一个文档的集合进行持续的跟踪并计算度量,而分块聚合则会进行块的构建,每个块都会跟一个键和一个文档查询条件关联起来。度量聚合的示例有平均值,最小值,最大值,加总值还有计数值。分块聚合的示例有范围、日期范围、直方图以及主题项。对聚合器更加深入的描述可以在这里找到。
  聚合可以放置在一个 aggregations 对象里面,而对象自己则是被直接放到 search 对象体中。在 aggregations 对象里面,每一个键都是由用户赋予一个聚合器的名称。聚合器的类型和其它选项都应该是作为这个键的值而放置的。接下来我们要来看看两个不同类型的聚合器,一个是度量的,一个块的。我们会用度量聚合器来尝试找出数据集合中最小的年份值(也就是最久远的文章),而使用块集合器我要做的就是尝试找出每一个关键词各自出现了多少次。
  在上述示例中,我们将度量聚合器命名为 min_year(也可以是其它名称), 也就是 year 这个域上的 min 类型。块聚合器责备命名为keywords, 就是 keywords 这个域上的 terms 类型。聚合操作的结果被装在了响应消息里的 aggregations 元素里面,更深入一点会发现里面包含了每一个聚合器(这里是 min_year 和 keywords)以及它们的聚合操作结果。 如下是来自这个示例响应消息中的部分内容。
  响应消息中默认最多会有10个块返回。你可以在请求中 filed 的边上加入一个size键来规定返回的块的最大数量。如果你想要接收到所有的块,可以将这个值设置为 0。
  建议
  Elasticsearch 提供了多种可以对输入内容提供替换和补全的关联项推荐器(见文档)。下面将介绍术语和短语推荐器。术语推荐器为每个输入文本中的术语提供关联推荐(如果有的话),而短语推荐器将整个输入文本看做一个短语(与将其拆分成术语对比),然后提供其他短语的推荐(如果有的话)。使用推荐API时,需要调用Node.js client的suggest方法。如下为术语推荐器的示例。
  与其他client的方法相同,在请求体中包含一个index字段指明采用的索引。在body字段中添加查询推荐的文本,然后给每个推荐器一个(包含了聚合对象的)名称(本例中的titleSuggester)。其值指明了推荐器的类型和配置。这里,为title字段使用了术语推荐器,限制最大建议的数量是每个token最多5个(size: 5)。
  建议API返回的数据中包含了对应请求中每一个建议器的key,其值是一个与你输入文本中术语数量相同的一个数组。对于数组中的每一个元素,包含一个options数组,其每个对象的text字段中包含了推荐的文本。如下是上面例子中返回数据的一部分。
  获取短语推荐的时候,采用与上文相同的格式并替换推荐器的类型字段即可。如下的例子中,返回数据将与上例格式相同。
  进一步阅读
  Elasticsearch 提供了许多特性,这些特性远远超出了这一篇文章所能讨论的范围。在这篇文章中,我试图站在一个很高的层次上来解释它的特性,并为你提供可用来进一步学习的合适资源。Elasticsearch是非常可靠的,并且有着出色的表现(我希望你在运行范例时已经注意到了这一点)。再加之不断增长的社区支持,使得Elasticsearch在工业中的应用也在不断增加,尤其是对于需要处理实时数据或大数据的公司。
  学习完这里提供的例子之后,我强烈建议你阅读一些相关文档。文档有两个主要来源,一是Elasticsearch参考及其特性,另外还有一个指南,它更多关注的是具体实现,使用案例以及最佳实践。更多文档和源码信息请点击“阅读原文”。
  END 查看全部

  如何用 Node.js 和 Elasticsearch 构建搜索引擎
  数据导入
  在本教程中,我将使用 1000 篇学术论文里的内容,这些内容是根据随机算法逐一生成的,并以 JSON 格式提供,其中的数据格式如下所示:
  JSON 格式中的每个字段如字面意思,无需多余解释,但值得注意的是:由于包含随机生成的文章的全部的内容(大概有100~200个段落),所以并未展示。
  虽然 Elasticsearch 提供了索引(indexing),更新(updating)、删除(deleting)单个数据的方法,但我们采用批量(bulk)接口导入数据,因为批量接口在大型数据集上执行操作的效率更高。
  这里,我们调用函数bulkIndex建立索引,并传入 3 个参数,分别是:索引名 library,类型名library,JSON 数据格式变量 articles。bulkIndex函数自身则通过调用esClient对象的bulk接口实现,bulk 方法包含一个body属性的对象参数,并且每个body属性值是一个包含 2 种操作实体的数组对象。第一个实体是 JSON 格式的操作类型对象,该对象中的index属性决定了操作的类型(本例子是文件索引)、索引名、文件ID。第二个实体则是文件对象本身。
  注意,后续可采用同样的方式,为其他类型文件(如书籍或者报告)添加索引。我们还可以有选择的每个文件分配一个唯一的ID,如果不体统唯一的ID,Elasticsearch 将主动为每个文件分配一个随机的唯一ID。
  假设你已经从代码库中下载了 Elasticsearch 项目代码,在项目根目录下执行如下命令,即可将数据导入至Elasticsearch中:
  检查数据的索引是否准确
  Elasticsearch 最大的特性是接近实时检索,这意味着,一旦文档索引建立完成,1 秒内就可被检索(见这里)。索引一旦建立完成,则可通过运行 indice.js 检查索引信息的准确性(源码链接):
  client 中的cat 对象方法提供当前运行实例的各种信息。其中的 indices 方法列出所有的索引信息,包括每个索引的健康状态、以及占用的磁盘大小。 而其中的 v 选项为 cat方法新增头部响应。
  当运行上面代码段,您会发现,集群的健康状态被不同的颜色标示。其中,红色表示为正常运行的有问题集群;黄色表示集群可运行,但存在告警;绿色表示集群正常运行。在本地运行上面的代码段,您极有可能(取决于您的配置)看到集群的健康状态颜色是黄色,这是因为默认的集群设置包含 5 个节点,但本地运行只有 1 个实例正常运行。鉴于本教程的目的仅局限于 Elasticsearch 指导学习,黄色即可。但在线上环境中,你必须确保集群的健康状态颜色是绿色的。
  动态和自定义映射
  如前所述, Elasticsearch 无模式(schema-free),这意味着,在数据导入之前,您无需定义数据的结构(类似于SQL数据库需要预先定义表结构),Elasticsearch 会主动检测。尽管 Elasticsearch 被定义为无模式,但数据结构上仍有些限制。
  Elasticsearch 以映射的方式引用数据结构。当数据索引建立完成后,如果映射不存在,Elasticsearch 会依次检索 JSON 数据的每个字段,然后基于被字段的类型(type)自动生成映射(mapping)。如果存在该字段的映射,则会确保按照同样的映射规则新增数据。否则直接报错。
  比如:如果{"key1": 12}已经存在,Elasticsearch 自动将字段 key1 映射为长整型。现在如果你尝试通过{"key1": "value1", "key2": "value2"} 检索, 则会直接报错,因为系统预期字段 key1 为长整型。同时,如果通过{"key1": 13, "key2": "value2"} 检索则不会报错,并为字段 key2 新增 string 类型。
  映射不能超出文本的范围,大都数情况下,系统自动生成的映射都可正常运行。
  构建搜索引擎
  一旦完成数据索引,我们就可以开始实现搜索引擎。Elasticsearch提供了一个直观的基于JSON的全搜索查询的结构-Query DSL,定义查询。有许多有用的搜索查询类型,但是在这篇文章中,我们将只看到几个通用的类型。关于Query DSL的完整文章可以在这里看到。
  请记住,我提供了每个展示例子的源码的连接。设置完你的环境和索引测试数据后,你可以下载源码,然后运行在你的机器上运行任何例子。可以通过命令行运行节点filename.js。
  
  返回一个或多个索引的所有记录
  为了执行我们的搜索,我们将使用客户端提供的多种搜索方法。最简单的查询是match_all,它可以返回一个或多个索引的所有的记录。下面的例子显示了我们怎么样获取在一个索引中获取所有存储的记录(源码).
  主要的搜索查询包含在Query对象中。就像我们接下来看到的那样,我们可以添加不同的搜索查询类型到这个对象。我们可以为每一个Query添加一个查询类型的关键字(如match_all),让这个Query成为一个包含搜索选项的对象。由于我们想返回索引的所有记录,所以在这个例子中没有查询选项。
  除了Query对象,搜索体中可以包含其他选项的属性,如size和from。size属性决定了返回记录的数量。如果这个值不存在,默认返回10个记录。from属性决定了返回记录的起始索引,这对分页有用。
  理解查询API的返回结果
  如果你打印搜索API返回结果(上面例子的结果)日志。由于它包含了很多信息,刚开始看起来无所适从。
  在最高级别日志输出里,返回结果中含有took属性,该属性值表示查找结果所用的毫秒数,timed_out只有在最大允许时间内没有找到结果时为true,_shards是不同节点的状态的信息(如果部署的是节点集群),hits是查询结果。
  hits的属性值是一个含有下列属性的对象:
  这十分复杂,但是好消息是一旦你实现了一个提取结果的方法,不管你的搜索查询结果时什么,你都可以使用相同的格式获取结果。
  还需要注意的是Elasticsearch有一个好处是它自动地给每一个匹配记录分配分数,这个分数用来量化文件的关联性,返回结果的顺序默认的按钮分数倒排。在例子中我们使用match_all取回了所有的记录,分数是没有意义的,所有的分数都被计算为1.0。
  匹配含指定字段值的文档
  现在我们看几个更加有趣的例子. 我们可以通过使用 match 关键字查询文档是否与指定的字段值匹配。一个最简单的包含 match 关键字的检索主体代码如下所示:
  如上文所述, 首先通过为查询对象新增一个条目,并指定检索类型,上面示例给的是 match 。然后再检索类型对象里面,申明待检索的文档对象,本例是 title 文档对象。然后再文档对象里面,提供相关检索数据,和 query 属性。我希望你测试过上述示例之后,惊讶于 Elasticsearch 的检索效率。
  上述示例执行成功后,将返回title(标题)字段与任一 query 属性词匹配的所有文档信息。同时还可以参考如下示例,为查询对象附加最小匹配数量条件:
  与该查询匹配的文档 title(标题)字段至少包含上诉指定的 3 个关键词。如果查询关键词少于 3个,那么匹配文档的 title(标题)字段必须包含所有的查询词。Elasticsearch 的另一个有用的功能是fuzziness(模糊匹配).这对于用户输入错误的查询词将非常有用,因为fuzzy(模糊匹配)将发现拼写错误并给出最接近词供选择。对于字符串类型,每个关键字的模糊匹配值是根据算法Levenshtein distance算出的最大允许值。fuzziness(模糊匹配)示例如下所示:
  多个字段搜索
  如果你想在多个字段中搜索,可以使用multi_match搜索类型。除了Query对象中的fields属性外,它同match有点类似。fields属性是需要搜索的字段的集合。这里我们将在title,authors.firstname, 和authors.lastname字段中搜索。
  multi_match查询支持其他搜索属性,如minimum_should_match和fuzziness。Elasticsearch支持使用通配符(如*)匹配字段,那么我们可以使用['title', 'authors.*name']把上面的例子变得更短些。
  匹配一个完整的句子
  Elasticsearch也支持精确的匹配一个输入的句子,而不是在单词级别。这个查询是在普通的match查询上扩展而来,叫做match_phrase。下面是一个match_phrase的例子
  
  联合多个查询
  到目前为止,在例子中我们每次请求只使用了单个查询。然而Elasticsearch允许你联合多个查询。最常用的复合查询是bool,bool查询接受4种关键类型must,should,must_not, 和filter.像它们的名字表示的那样,在查询结果的数据里必须匹配must里的查询,必须不匹配must_not里的查询,如果哪个数据匹配should里的查询,它就会获得高分。每一个提到的元素可以使用查询数组格式接受多个搜索查询。
  下面,我们使用bool查询及一个新的叫做query_string的查询类型。它允许你使用AND或OR写一些比较高级的查询。另外,我们使用了range查询,它可以让我们通过给定的范围的方式去限制一个字段。
  在上面的例子中,查询返回的数据,作者的名包含term1或它们的姓包含term2,并且它们的title含有term3,而且它们不在2011,2012或2013年出版的,还有在body字段里含有给定句子数据将获得高分,并被排列到结果的前面(由于在should从句中的match查询)。
  过滤,聚合,和建议
  除了它先进的搜索功能外,Elasticsearch还提供了其他的功能。接下来,我们再看看其他三个比较常用的功能。
  过滤
  也许,你经常想使用特定的条件凝缩查询结果。Elasticsearch通过filters提供了这样的功能。在我们的文章数据里,假设你的查询返回了几个文章,这些文章是你选择的在5个具体年份发布的文章。你可以简单的从搜索结果中过滤出那些不匹配条件的数据,而不改变查询结果的顺序。
  在bool查询的must从句中,过滤和相同查询之间的不同之处在于,过滤不会影响搜索分数,而must查询会。当查询结果返回并且用户使用给定的条件过滤时,他们不想改变结果的顺序,相反地,他们只想从结果中移除不相关的数据。过滤与搜索的格式一样,但在通常情况下,他们在有明确值的字段上定义,而不是文本字符串上。Elasticsearch推荐通过bool复合查询的filter从句添加过滤。
  继续看上面的例子,假设我们想把搜索结果限制在在2011到2015年之间发布的文章里。这样做,我们只需要在一般搜索查询的filter部分添加range查询。这将会从结果中移除那些不匹配的数据。下面是一个过滤查询的例子
  聚合
  聚合框架会基于一次搜索查询,提供各种聚合数据和统计信息。两个主要的聚合类型是度量和分块, 度量聚合会对一个文档的集合进行持续的跟踪并计算度量,而分块聚合则会进行块的构建,每个块都会跟一个键和一个文档查询条件关联起来。度量聚合的示例有平均值,最小值,最大值,加总值还有计数值。分块聚合的示例有范围、日期范围、直方图以及主题项。对聚合器更加深入的描述可以在这里找到。
  聚合可以放置在一个 aggregations 对象里面,而对象自己则是被直接放到 search 对象体中。在 aggregations 对象里面,每一个键都是由用户赋予一个聚合器的名称。聚合器的类型和其它选项都应该是作为这个键的值而放置的。接下来我们要来看看两个不同类型的聚合器,一个是度量的,一个块的。我们会用度量聚合器来尝试找出数据集合中最小的年份值(也就是最久远的文章),而使用块集合器我要做的就是尝试找出每一个关键词各自出现了多少次。
  在上述示例中,我们将度量聚合器命名为 min_year(也可以是其它名称), 也就是 year 这个域上的 min 类型。块聚合器责备命名为keywords, 就是 keywords 这个域上的 terms 类型。聚合操作的结果被装在了响应消息里的 aggregations 元素里面,更深入一点会发现里面包含了每一个聚合器(这里是 min_year 和 keywords)以及它们的聚合操作结果。 如下是来自这个示例响应消息中的部分内容。
  响应消息中默认最多会有10个块返回。你可以在请求中 filed 的边上加入一个size键来规定返回的块的最大数量。如果你想要接收到所有的块,可以将这个值设置为 0。
  建议
  Elasticsearch 提供了多种可以对输入内容提供替换和补全的关联项推荐器(见文档)。下面将介绍术语和短语推荐器。术语推荐器为每个输入文本中的术语提供关联推荐(如果有的话),而短语推荐器将整个输入文本看做一个短语(与将其拆分成术语对比),然后提供其他短语的推荐(如果有的话)。使用推荐API时,需要调用Node.js client的suggest方法。如下为术语推荐器的示例。
  与其他client的方法相同,在请求体中包含一个index字段指明采用的索引。在body字段中添加查询推荐的文本,然后给每个推荐器一个(包含了聚合对象的)名称(本例中的titleSuggester)。其值指明了推荐器的类型和配置。这里,为title字段使用了术语推荐器,限制最大建议的数量是每个token最多5个(size: 5)。
  建议API返回的数据中包含了对应请求中每一个建议器的key,其值是一个与你输入文本中术语数量相同的一个数组。对于数组中的每一个元素,包含一个options数组,其每个对象的text字段中包含了推荐的文本。如下是上面例子中返回数据的一部分。
  获取短语推荐的时候,采用与上文相同的格式并替换推荐器的类型字段即可。如下的例子中,返回数据将与上例格式相同。
  进一步阅读
  Elasticsearch 提供了许多特性,这些特性远远超出了这一篇文章所能讨论的范围。在这篇文章中,我试图站在一个很高的层次上来解释它的特性,并为你提供可用来进一步学习的合适资源。Elasticsearch是非常可靠的,并且有着出色的表现(我希望你在运行范例时已经注意到了这一点)。再加之不断增长的社区支持,使得Elasticsearch在工业中的应用也在不断增加,尤其是对于需要处理实时数据或大数据的公司。
  学习完这里提供的例子之后,我强烈建议你阅读一些相关文档。文档有两个主要来源,一是Elasticsearch参考及其特性,另外还有一个指南,它更多关注的是具体实现,使用案例以及最佳实践。更多文档和源码信息请点击“阅读原文”。
  END

小技巧!前端JS实现过滤指定内容~

网站优化优采云 发表了文章 • 0 个评论 • 67 次浏览 • 2022-07-02 03:46 • 来自相关话题

  小技巧!前端JS实现过滤指定内容~
  小技巧!前端JS实现过滤指定内容~
  原创氧气 ☞☞☞
  执行上下文
  JsCoding
  一枚佛系前端开发,会一丢丢摄影,喜欢折腾,爱好美食,分享点学习经验、见闻、笔记、技巧!
  发表于
  收录于合集#前端日常问题合集11个
  戳上方“执行上下文”,选择“置顶公众号”
  关键时刻,第一时间送达!
  
  1、JS实现验证码倒计时
  /*点击获取验证码*/<br />$(".addCode").click(function(event) {<br />    var addCode = $(".addCode")<br />    verificationCode(addCode);<br />});<br />/*验证码的方法*/<br />function verificationCode(name) {<br />    var num = 20;<br />    var timer = setInterval(function() {<br />        num--;<br />        name.attr("disabled", "disabled").html(num + '秒后重试');<br />        if (num == 0) {<br />            clearInterval(timer);<br />            name.attr("disabled", false).html("重新获取");<br />        }<br />    }, 1000)<br />}<br />
  2、CSS实现文字分散对齐
  注意:只支持高版本Chrome浏览器
  text-align-last:justify;<br />text-align:justify;<br />text-justify:distribute-all-lines;<br />
  3、JS过滤指定内容
  function replaceText(words) {<br />   <br />    let text = '你是个傻逼,我才不想你这个傻逼呢。大傻逼!'<br />    for (var i = 0; i  min) {<br />        index = Math.floor((i + 1) * Math.random());<br />        item = sData[index];<br />        sData[index] = sData[i];<br />        sData[i] = item;<br />    }<br />    return sData.slice(min);<br />}<br /><br />getRandomArrayValue(groups, 4)<br /><br />// ["7", "8", "10", "2"]<br />
  前端公众号和交流群 查看全部

  小技巧!前端JS实现过滤指定内容~
  小技巧!前端JS实现过滤指定内容~
  原创氧气 ☞☞☞
  执行上下文
  JsCoding
  一枚佛系前端开发,会一丢丢摄影,喜欢折腾,爱好美食,分享点学习经验、见闻、笔记、技巧!
  发表于
  收录于合集#前端日常问题合集11个
  戳上方“执行上下文”,选择“置顶公众号”
  关键时刻,第一时间送达!
  
  1、JS实现验证码倒计时
  /*点击获取验证码*/<br />$(".addCode").click(function(event) {<br />    var addCode = $(".addCode")<br />    verificationCode(addCode);<br />});<br />/*验证码的方法*/<br />function verificationCode(name) {<br />    var num = 20;<br />    var timer = setInterval(function() {<br />        num--;<br />        name.attr("disabled", "disabled").html(num + '秒后重试');<br />        if (num == 0) {<br />            clearInterval(timer);<br />            name.attr("disabled", false).html("重新获取");<br />        }<br />    }, 1000)<br />}<br />
  2、CSS实现文字分散对齐
  注意:只支持高版本Chrome浏览器
  text-align-last:justify;<br />text-align:justify;<br />text-justify:distribute-all-lines;<br />
  3、JS过滤指定内容
  function replaceText(words) {<br />   <br />    let text = '你是个傻逼,我才不想你这个傻逼呢。大傻逼!'<br />    for (var i = 0; i  min) {<br />        index = Math.floor((i + 1) * Math.random());<br />        item = sData[index];<br />        sData[index] = sData[i];<br />        sData[i] = item;<br />    }<br />    return sData.slice(min);<br />}<br /><br />getRandomArrayValue(groups, 4)<br /><br />// ["7", "8", "10", "2"]<br />
  前端公众号和交流群

js提取指定网站内容 谈谈对vitejs预构建的理解

网站优化优采云 发表了文章 • 0 个评论 • 109 次浏览 • 2022-06-29 21:43 • 来自相关话题

  js提取指定网站内容 谈谈对vitejs预构建的理解
  vite在官网介绍中,第一条就提到的特性就是自己的本地冷启动极快。这主要是得益于它在本地服务启动的时候做了预构建。出于好奇,抽时间了解了下vite在预构建部分的主要实现思路,分享出来供大家参考。
  为啥要预构建
  简单来讲就是为了提高本地开发服务器的冷启动速度。按照vite的说法,当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。随着应用规模的增大,打包速度显著下降,本地服务器的启动速度也跟着变慢。
  为了加快本地开发服务器的启动速度,vite引入了预构建机制。在预构建工具的选择上,vite选择了esbuild。esbuild使用Go编写,比以JavaScript编写的打包器构建速度快 10-100 倍,有了预构建,再利用浏览器的esm方式按需加载业务代码,动态实时进行构建,结合缓存机制,大大提升了服务器的启动速度。
  
  预构建的流程1. 查找依赖
  如果是首次启动本地服务,那么vite会自动抓取源代码,从代码中找到需要预构建的依赖,最终对外返回类似下面的一个deps对象:
  { vue: '/path/to/your/project/node_modules/vue/dist/vue.runtime.esm-bundler.js', 'element-plus': '/path/to/your/project/node_modules/element-plus/es/index.mjs', 'vue-router': '/path/to/your/project/node_modules/vue-router/dist/vue-router.esm-bundler.js'}
  具体实现就是,调用esbuild的buildapi,以index.html作为查找入口(entryPoints),将所有的来自node_modules以及在配置文件的optimizeDeps.include选项中指定的模块找出来。
  //...省略其他代码 if (explicitEntryPatterns) { entries = await globEntries(explicitEntryPatterns, config) } else if (buildInput) { const resolvePath = (p: string) => path.resolve(config.root, p) if (typeof buildInput === 'string') { entries = [resolvePath(buildInput)] } else if (Array.isArray(buildInput)) { entries = buildInput.map(resolvePath) } else if (isObject(buildInput)) { entries = Object.values(buildInput).map(resolvePath) } else { throw new Error('invalid rollupOptions.input value.') } } else { // 重点看这里:使用html文件作为查找入口 entries = await globEntries('**/*.html', config) } //...省略其他代码build.onResolve( { // avoid matching windows volume filter: /^[\w@][^:]/ }, async ({ path: id, importer }) => { const resolved = await resolve(id, importer) if (resolved) { // 来自node_modules和在include中指定的模块 if (resolved.includes('node_modules') || include?.includes(id)) { // dependency or forced included, externalize and stop crawling<br /> if (isOptimizable(resolved)) { // 重点看这里:将符合预构建条件的依赖记录下来,depImports就是对外导出的需要预构建的依赖对象 depImports[id] = resolved } return externalUnlessEntry({ path: id }) } else if (isScannable(resolved)) { const namespace = htmlTypesRE.test(resolved) ? 'html' : undefined // linked package, keep crawling return { path: path.resolve(resolved), namespace } } else { return externalUnlessEntry({ path: id }) } } else { missing[id] = normalizePath(importer) } } )
  但是熟悉esbuild的小伙伴可能知道,esbuild默认支持的入口文件类型有js、ts、jsx、css、json、base64、dataurl、binary、file(.png等),并不包括html。vite是如何做到将index.html作为打包入口的呢?原因是vite自己实现了一个esbuild插件esbuildScanPlugin,来处理.vue和.html这种类型的文件。具体做法是读取html的内容,然后将里面的script提取到一个esm格式的js模块。
  
   // 对于html类型(.VUE/.HTML/.svelte等)的文件,提取文件里的script内容。html types: extract script contents ----------------------------------- build.onResolve({ filter: htmlTypesRE }, async ({ path, importer }) => { const resolved = await resolve(path, importer) if (!resolved) return // It is possible for the scanner to scan html types in node_modules. // If we can optimize this html type, skip it so it's handled by the // bare import resolve, and recorded as optimization dep. if (resolved.includes('node_modules') && isOptimizable(resolved)) return return { path: resolved, namespace: 'html' } })<br /> // 配合build.onResolve,对于类html文件,提取其中的script,作为一个js模块extract scripts inside HTML-like files and treat it as a js module build.onLoad( { filter: htmlTypesRE, namespace: 'html' }, async ({ path }) => { let raw = fs.readFileSync(path, 'utf-8') // Avoid matching the content of the comment raw = raw.replace(commentRE, '') const isHtml = path.endsWith('.html') const regex = isHtml ? scriptModuleRE : scriptRE regex.lastIndex = 0 // js 的内容被处理成了一个虚拟模块 let js = '' let scriptId = 0 let match: RegExpExecArray | null while ((match = regex.exec(raw))) { const [, openTag, content] = match const typeMatch = openTag.match(typeRE) const type = typeMatch && (typeMatch[1] || typeMatch[2] || typeMatch[3]) const langMatch = openTag.match(langRE) const lang = langMatch && (langMatch[1] || langMatch[2] || langMatch[3]) // skip type="application/ld+json" and other non-JS types if ( type && !( type.includes('javascript') || type.includes('ecmascript') || type === 'module' ) ) { continue } // 默认的js文件的loader是js,其他对于ts、tsx jsx有对应的同名loader let loader: Loader = 'js' if (lang === 'ts' || lang === 'tsx' || lang === 'jsx') { loader = lang } const srcMatch = openTag.match(srcRE) // 对于引入的js,将它转换为import 'path/to/some.js'的代码 if (srcMatch) { const src = srcMatch[1] || srcMatch[2] || srcMatch[3] js += `import ${JSON.stringify(src)}\n` } else if (content.trim()) { // The reason why virtual modules are needed: // 1. There can be module scripts (`` in Svelte and `` in Vue) // or local scripts (`` in Svelte and `` in Vue) // 2. There can be multiple module scripts in html // We need to handle these separately in case variable names are reused between them<br /> // append imports in TS to prevent esbuild from removing them // since they may be used in the template const contents = content + (loader.startsWith('ts') ? extractImportPaths(content) : '')<br /> // 将提取出来的script脚本,存在以xx.vue?id=1为key的script对象中script={'xx.vue?id=1': 'js contents'} const key = `${path}?id=${scriptId++}`<br /> if (contents.includes('import.meta.glob')) { scripts[key] = { // transformGlob already transforms to js loader: 'js', contents: await transformGlob( contents, path, config.root, loader, resolve, config.logger ) } } else { scripts[key] = { loader, contents } }<br /> const virtualModulePath = JSON.stringify( virtualModulePrefix + key )<br /> const contextMatch = openTag.match(contextRE) const context = contextMatch && (contextMatch[1] || contextMatch[2] || contextMatch[3])<br /> // Especially for Svelte files, exports in means module exports, // exports in means component props. To avoid having two same export name from the // star exports, we need to ignore exports in if (path.endsWith('.svelte') && context !== 'module') { js += `import ${virtualModulePath}\n` } else { // e.g. export * from 'virtual-module:xx.vue?id=1' js += `export * from ${virtualModulePath}\n` } } }<br /> // This will trigger incorrectly if `export default` is contained // anywhere in a string. Svelte and Astro files can't have // `export default` as code so we know if it's encountered it's a // false positive (e.g. contained in a string) if (!path.endsWith('.vue') || !js.includes('export default')) { js += '\nexport default {}' }<br /> return { loader: 'js', contents: js } } )
  由上文我们可知,来自node_modules中的模块依赖是需要预构建的。例如import ElementPlus from 'element-plus'。因为在浏览器环境下,是不支持这种裸模块引用的(bare import)。另一方面,如果不进行构建,浏览器面对由成百上千的子模块组成的依赖,依靠原生esm的加载机制,每个的依赖的import都将产生一次http请求。面对大量的请求,浏览器是吃不消的。因此客观上需要对裸模块引入进行打包,并处理成浏览器环境下支持的相对路径或路径的导入方式。例如:import ElementPlus from '/path/to/.vite/element-plus/es/index.mjs'。
  2. 对查找到的依赖进行构建
  在上一步,已经得到了需要预构建的依赖列表。现在需要把他们作为esbuild的entryPoints打包就行了。
  //使用esbuild打包,入口文件即为第一步中抓取到的需要预构建的依赖 import { build } from 'esbuild' // ...省略其他代码 const result = await build({ absWorkingDir: process.cwd(), // flatIdDeps即为第一步中所得到的需要预构建的依赖对象 entryPoints: Object.keys(flatIdDeps), bundle: true, format: 'esm', target: config.build.target || undefined, external: config.optimizeDeps?.exclude, logLevel: 'error', splitting: true, sourcemap: true,// outdir指定打包产物输出目录,processingCacheDir这里并不是.vite,而是存放构建产物的临时目录 outdir: processingCacheDir, ignoreAnnotations: true, metafile: true, define, plugins: [ ...plugins, esbuildDepPlugin(flatIdDeps, flatIdToExports, config, ssr) ], ...esbuildOptions })<br /> // 写入_metadata文件,并替换缓存文件。Write metadata file, delete `deps` folder and rename the new `processing` folder to `deps` in sync commitProcessingDepsCacheSync()
  vite并没有将esbuild的outdir(构建产物的输出目录)直接配置为.vite目录,而是先将构建产物存放到了一个临时目录。当构建完成后,才将原来旧的.vite(如果有的话)删除。然后再将临时目录重命名为.vite。这样做主要是为了避免在程序运行过程中发生了错误,导致缓存不可用。
   function commitProcessingDepsCacheSync() { // Rewire the file paths from the temporal processing dir to the final deps cache dir const dataPath = path.join(processingCacheDir, '_metadata.json') writeFile(dataPath, stringifyOptimizedDepsMetadata(metadata)) // Processing is done, we can now replace the depsCacheDir with processingCacheDir // 依赖处理完成后,使用依赖缓存目录替换处理中的依赖缓存目录 if (fs.existsSync(depsCacheDir)) { const rmSync = fs.rmSync ?? fs.rmdirSync // TODO: Remove after support for Node 12 is dropped rmSync(depsCacheDir, { recursive: true }) } fs.renameSync(processingCacheDir, depsCacheDir) }} 查看全部

  js提取指定网站内容 谈谈对vitejs预构建的理解
  vite在官网介绍中,第一条就提到的特性就是自己的本地冷启动极快。这主要是得益于它在本地服务启动的时候做了预构建。出于好奇,抽时间了解了下vite在预构建部分的主要实现思路,分享出来供大家参考。
  为啥要预构建
  简单来讲就是为了提高本地开发服务器的冷启动速度。按照vite的说法,当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。随着应用规模的增大,打包速度显著下降,本地服务器的启动速度也跟着变慢。
  为了加快本地开发服务器的启动速度,vite引入了预构建机制。在预构建工具的选择上,vite选择了esbuild。esbuild使用Go编写,比以JavaScript编写的打包器构建速度快 10-100 倍,有了预构建,再利用浏览器的esm方式按需加载业务代码,动态实时进行构建,结合缓存机制,大大提升了服务器的启动速度。
  
  预构建的流程1. 查找依赖
  如果是首次启动本地服务,那么vite会自动抓取源代码,从代码中找到需要预构建的依赖,最终对外返回类似下面的一个deps对象:
  { vue: '/path/to/your/project/node_modules/vue/dist/vue.runtime.esm-bundler.js', 'element-plus': '/path/to/your/project/node_modules/element-plus/es/index.mjs', 'vue-router': '/path/to/your/project/node_modules/vue-router/dist/vue-router.esm-bundler.js'}
  具体实现就是,调用esbuild的buildapi,以index.html作为查找入口(entryPoints),将所有的来自node_modules以及在配置文件的optimizeDeps.include选项中指定的模块找出来。
  //...省略其他代码 if (explicitEntryPatterns) { entries = await globEntries(explicitEntryPatterns, config) } else if (buildInput) { const resolvePath = (p: string) => path.resolve(config.root, p) if (typeof buildInput === 'string') { entries = [resolvePath(buildInput)] } else if (Array.isArray(buildInput)) { entries = buildInput.map(resolvePath) } else if (isObject(buildInput)) { entries = Object.values(buildInput).map(resolvePath) } else { throw new Error('invalid rollupOptions.input value.') } } else { // 重点看这里:使用html文件作为查找入口 entries = await globEntries('**/*.html', config) } //...省略其他代码build.onResolve( { // avoid matching windows volume filter: /^[\w@][^:]/ }, async ({ path: id, importer }) => { const resolved = await resolve(id, importer) if (resolved) { // 来自node_modules和在include中指定的模块 if (resolved.includes('node_modules') || include?.includes(id)) { // dependency or forced included, externalize and stop crawling<br /> if (isOptimizable(resolved)) { // 重点看这里:将符合预构建条件的依赖记录下来,depImports就是对外导出的需要预构建的依赖对象 depImports[id] = resolved } return externalUnlessEntry({ path: id }) } else if (isScannable(resolved)) { const namespace = htmlTypesRE.test(resolved) ? 'html' : undefined // linked package, keep crawling return { path: path.resolve(resolved), namespace } } else { return externalUnlessEntry({ path: id }) } } else { missing[id] = normalizePath(importer) } } )
  但是熟悉esbuild的小伙伴可能知道,esbuild默认支持的入口文件类型有js、ts、jsx、css、json、base64、dataurl、binary、file(.png等),并不包括html。vite是如何做到将index.html作为打包入口的呢?原因是vite自己实现了一个esbuild插件esbuildScanPlugin,来处理.vue和.html这种类型的文件。具体做法是读取html的内容,然后将里面的script提取到一个esm格式的js模块。
  
   // 对于html类型(.VUE/.HTML/.svelte等)的文件,提取文件里的script内容。html types: extract script contents ----------------------------------- build.onResolve({ filter: htmlTypesRE }, async ({ path, importer }) => { const resolved = await resolve(path, importer) if (!resolved) return // It is possible for the scanner to scan html types in node_modules. // If we can optimize this html type, skip it so it's handled by the // bare import resolve, and recorded as optimization dep. if (resolved.includes('node_modules') && isOptimizable(resolved)) return return { path: resolved, namespace: 'html' } })<br /> // 配合build.onResolve,对于类html文件,提取其中的script,作为一个js模块extract scripts inside HTML-like files and treat it as a js module build.onLoad( { filter: htmlTypesRE, namespace: 'html' }, async ({ path }) => { let raw = fs.readFileSync(path, 'utf-8') // Avoid matching the content of the comment raw = raw.replace(commentRE, '') const isHtml = path.endsWith('.html') const regex = isHtml ? scriptModuleRE : scriptRE regex.lastIndex = 0 // js 的内容被处理成了一个虚拟模块 let js = '' let scriptId = 0 let match: RegExpExecArray | null while ((match = regex.exec(raw))) { const [, openTag, content] = match const typeMatch = openTag.match(typeRE) const type = typeMatch && (typeMatch[1] || typeMatch[2] || typeMatch[3]) const langMatch = openTag.match(langRE) const lang = langMatch && (langMatch[1] || langMatch[2] || langMatch[3]) // skip type="application/ld+json" and other non-JS types if ( type && !( type.includes('javascript') || type.includes('ecmascript') || type === 'module' ) ) { continue } // 默认的js文件的loader是js,其他对于ts、tsx jsx有对应的同名loader let loader: Loader = 'js' if (lang === 'ts' || lang === 'tsx' || lang === 'jsx') { loader = lang } const srcMatch = openTag.match(srcRE) // 对于引入的js,将它转换为import 'path/to/some.js'的代码 if (srcMatch) { const src = srcMatch[1] || srcMatch[2] || srcMatch[3] js += `import ${JSON.stringify(src)}\n` } else if (content.trim()) { // The reason why virtual modules are needed: // 1. There can be module scripts (`` in Svelte and `` in Vue) // or local scripts (`` in Svelte and `` in Vue) // 2. There can be multiple module scripts in html // We need to handle these separately in case variable names are reused between them<br /> // append imports in TS to prevent esbuild from removing them // since they may be used in the template const contents = content + (loader.startsWith('ts') ? extractImportPaths(content) : '')<br /> // 将提取出来的script脚本,存在以xx.vue?id=1为key的script对象中script={'xx.vue?id=1': 'js contents'} const key = `${path}?id=${scriptId++}`<br /> if (contents.includes('import.meta.glob')) { scripts[key] = { // transformGlob already transforms to js loader: 'js', contents: await transformGlob( contents, path, config.root, loader, resolve, config.logger ) } } else { scripts[key] = { loader, contents } }<br /> const virtualModulePath = JSON.stringify( virtualModulePrefix + key )<br /> const contextMatch = openTag.match(contextRE) const context = contextMatch && (contextMatch[1] || contextMatch[2] || contextMatch[3])<br /> // Especially for Svelte files, exports in means module exports, // exports in means component props. To avoid having two same export name from the // star exports, we need to ignore exports in if (path.endsWith('.svelte') && context !== 'module') { js += `import ${virtualModulePath}\n` } else { // e.g. export * from 'virtual-module:xx.vue?id=1' js += `export * from ${virtualModulePath}\n` } } }<br /> // This will trigger incorrectly if `export default` is contained // anywhere in a string. Svelte and Astro files can't have // `export default` as code so we know if it's encountered it's a // false positive (e.g. contained in a string) if (!path.endsWith('.vue') || !js.includes('export default')) { js += '\nexport default {}' }<br /> return { loader: 'js', contents: js } } )
  由上文我们可知,来自node_modules中的模块依赖是需要预构建的。例如import ElementPlus from 'element-plus'。因为在浏览器环境下,是不支持这种裸模块引用的(bare import)。另一方面,如果不进行构建,浏览器面对由成百上千的子模块组成的依赖,依靠原生esm的加载机制,每个的依赖的import都将产生一次http请求。面对大量的请求,浏览器是吃不消的。因此客观上需要对裸模块引入进行打包,并处理成浏览器环境下支持的相对路径或路径的导入方式。例如:import ElementPlus from '/path/to/.vite/element-plus/es/index.mjs'。
  2. 对查找到的依赖进行构建
  在上一步,已经得到了需要预构建的依赖列表。现在需要把他们作为esbuild的entryPoints打包就行了。
  //使用esbuild打包,入口文件即为第一步中抓取到的需要预构建的依赖 import { build } from 'esbuild' // ...省略其他代码 const result = await build({ absWorkingDir: process.cwd(), // flatIdDeps即为第一步中所得到的需要预构建的依赖对象 entryPoints: Object.keys(flatIdDeps), bundle: true, format: 'esm', target: config.build.target || undefined, external: config.optimizeDeps?.exclude, logLevel: 'error', splitting: true, sourcemap: true,// outdir指定打包产物输出目录,processingCacheDir这里并不是.vite,而是存放构建产物的临时目录 outdir: processingCacheDir, ignoreAnnotations: true, metafile: true, define, plugins: [ ...plugins, esbuildDepPlugin(flatIdDeps, flatIdToExports, config, ssr) ], ...esbuildOptions })<br /> // 写入_metadata文件,并替换缓存文件。Write metadata file, delete `deps` folder and rename the new `processing` folder to `deps` in sync commitProcessingDepsCacheSync()
  vite并没有将esbuild的outdir(构建产物的输出目录)直接配置为.vite目录,而是先将构建产物存放到了一个临时目录。当构建完成后,才将原来旧的.vite(如果有的话)删除。然后再将临时目录重命名为.vite。这样做主要是为了避免在程序运行过程中发生了错误,导致缓存不可用。
   function commitProcessingDepsCacheSync() { // Rewire the file paths from the temporal processing dir to the final deps cache dir const dataPath = path.join(processingCacheDir, '_metadata.json') writeFile(dataPath, stringifyOptimizedDepsMetadata(metadata)) // Processing is done, we can now replace the depsCacheDir with processingCacheDir // 依赖处理完成后,使用依赖缓存目录替换处理中的依赖缓存目录 if (fs.existsSync(depsCacheDir)) { const rmSync = fs.rmSync ?? fs.rmdirSync // TODO: Remove after support for Node 12 is dropped rmSync(depsCacheDir, { recursive: true }) } fs.renameSync(processingCacheDir, depsCacheDir) }}

js提取指定网站内容 JavaScript SEO 终极指南(Google SEOer必看)

网站优化优采云 发表了文章 • 0 个评论 • 132 次浏览 • 2022-06-29 06:10 • 来自相关话题

  js提取指定网站内容 JavaScript SEO 终极指南(Google SEOer必看)
  5.分类筛选器
  所以,如果这些内容在JavaScript 上没有处理好的话,很容易造成索引及排名上遇到困难。
  那如何检查网页上哪些内容是JavaScript 所产生的呢
  一、通过使用Chrome 插件:
  这边介绍的工具叫做『Quick Javascript Switcher』,这个插件可以直接开关网页的JavaScript 功能,只要你关掉JavaScript 后,发现哪个部分的内容不见了,那很大程度就是那个内容是JavaScript 所产生。
  从下图可以看到,当我们用插件关掉JavaScript 功能后,Pressplay 的主要内容消失不见了,那就代表说其中主要内容由JavaScript 所产生。
  二、从开发者工具关闭
  首先点击鼠标右键找到『检查』,你会进入开发者介面。
  接着使用快捷键『Control + Shift + p』 (Windows) 或是『Command + Option + p』 (Mac)。
  接着在光标处中输入JavaScript,就会看到一个『Disable JavaScript』选项,点击即可关闭JavaScript,同理要再打开只需使用相同方法再点击一次便可打开JavaScript 功能。
  为什么网页源代码没有JavaScript 产生的内容!?
  一般来说,我们在检查网页中的meta 标签、H 标签等内容时,最常做的就是从网页源代码中去查看,也就是『右键> 检查网页源代码』所呈现的内容。
  而这个文件就是HTML 文件,但这份HTML 文件仅仅代表浏览器在解析页面时的最初讯息,而JavaScript 所产生的内容并不在一开始的HTML 文件上。
  所以,检查网页源代码无法知道JavaScript 更新后的动态内容。
  此时就要介绍一下HTML 加工后的DOM 了,这边为了不复杂化,简单叙述一下,当你『右键> 检查』出来的东西便是加工过的DOM(如下图)。DOM 里面会随着你与网站的互动,将JavaScript 所产生的内容加上去。
  那如何区分HTML 源代码还是加工后的DOM 呢?
  PS: 如果Google 爬取页面时无法完整呈现JavaScript 产生的页面,它至少可以索引为加载过的HTML 原始码。
  在确认并且知道哪些内容属于JavaScript 所产生的之后,再就是理解Google 怎么爬取JavaScript,并且优化你的内容让网页排名上升。
  二、Google 怎么爬取JS 网站
  对于搜索引擎而言,JavaScript 一直是Google 努力在改善爬虫技术,让搜索引擎索引并排名的目标之一。虽然JavaScript 为访客带来更良好的使用体验,但是对于搜索引擎而言却不是一件容易的事情,请记得:
  根据onely 网站调查指出,许多大品牌网页上JavaScript 之内容未被索引的情况:
  你可以想像,Yoox 在国外是知名电商网站,每个月可以有高达1400 万的流量,但是网站由JavaScript 产生的内容竟然由高达92% 是Google 不会索引到的,由此可知这样对SEO 的影响可以有多大,损失又可以有多多。
  但同样的,也有把JavaScript 所产生的内容处理的很好的网站, 以及 的网站分别让JavaScript 所产生的内容,被100% 及99% 的索引了,所以,只要方法得当,我们也能让JavaScript 与SEO 兼顾。
  Google 爬取页面的过程
  在早期搜索引擎只需要下载HTML 档便可完整了解网页内容,但由于JavaScript 技术的崛起及普及,搜索引擎甚至需要像浏览器一样,以便他们以访客的角度查看网页内容。
  而Google 处理渲染的系统,被称为Web Rendering Service (WRS),中文可以翻译成网页渲染器,后面以WRS 代称,而Google 也给出了一张简化的图作为说明。
  简单说明Google 爬取步骤,传统爬取HTML 档页面时,每项元素都很好爬取,整个索引并排名页面的过程也迅速:
  1.Google bot 下载HTML 档
  2.Google bot 从源代码中提取url 网址,并快速访问这些url
  3.Google bot 下载CSS 档案
  4.Google bot 将下载下来的资源送到Google 的Indexer
  5.Google 的Indexer 检索页面
  但如果是今天爬取JavaScript 所产生的网站内容的话,Google 会怎么爬取呢:
  1.Google bot 下载HTML 档
  2.Google bot 在源代码中找不到链接,因为JavaScript 未被执行
  3.Google bot 下载CSS 及JavaScript 档案
  4.Google bot 使用WRS(渲染器,Indexer 的一部分)解析、编译并执行JavaScript
  5.WRS 从外部API、资料库获取资料(data)
  6.Indexer 可以索引内容
  7.Google 发现新的链接,并将其加入爬取排队队伍之中(Googlebot's crawling queue)。至此,执行一般Google bot 爬取HTML 页面的第二步。
  可以发现,为了渲染出页面,Google 多了许多步骤。再来讲一下渲染过程中,Crawler、Processing、Renderer 及Index 之重要节点。
  三、Google 爬取JavaScript 过程中的重要节点
  Crawler(爬虫)
  首先,crawler 会先向网站服务器发送一段请求(request),网站服务器会返回内容及其标头(header),然后crawler 将它储存起来。
  而由于mobile-first indexing的关系,发送请求的可能大多都是来自手机版的爬虫(mobile user-agent),从Google Search Console上可以检查到,你可以透过网址审查或是涵盖范围来知道现在是电脑版索引还是手机版优先索引的状态。
  然后有些网站会使用user-agent detection,侦测访客来到自己网站时,是用手机还是桌机、浏览器是什么、浏览器版本的不同资讯,再根据这些资讯给访客相对应的资讯,例如今天侦测到访客是用手机版本的chrome,便呈现手机版的页面给访客看。
  需要注意的是,有些网站遇到爬虫时可能会设定禁止该爬虫爬取页面,或是禁止特定地区ip 的访客查看页面,这时候就要小心如果网页没设定好的话,很有可能爬虫是看不到你的内容的喔。
  记得从几个方面测试看看Google 爬虫能否顺利看到你的页面:Google Search Console 的网址检查器、移动友好测试工具以及富媒体结果测试工具。
  补充:从爬取过程那张图可以看到,Google 将爬取后产生的页面称之为HTML,但实际上,为了建构页面内容,Google 其实爬取并储存了相关所需的资源,像是CSS 文档、JS 文档、API 端口、XHR requests等相关资源。
  Processing(处理)
  Processing 的过程中其实是非常复杂且处理很多事的,这边重点讲述Google 处理JavaScript 的过程。
  (一)遵循限制性最高的要求
  什么是限制性最高的要求,就是假设今天Google 渲染(render)出页面后,原本meta robots 的信息是index 被加入了noindex,那么Google 将不会索引其页面,甚至其它尚未被渲染的页面,因为JS 产生noindex 这类的语法,则可能导致页面无法被渲染。
  (二)处理资源及链接
  Google 并不像访客那样浏览页面,Processing 的过程中有个很重要的工作便是检查页面上的链接以及建构该页面所需的文档。
  这些链接被记录,加到等待爬取的排队序列中(crawl queue),反覆执行找链接、链接排队、爬取链接,便是Google 本身爬取整个网路世界的方式。
  Google 透过属性,将建构页面所需的资源,像是JS、CSS 文档被记录。但是页面对页面的链接需要以特定的形式所呈现,才能被Google 所抓取,那就是以链接”>的形式。
  
  能被爬取的連結a>
  不能被爬取的連結span>
  不能被爬取的連結a>
  能被爬取的連結a>
  如果你的链接是JavaScript 所产生的话,那必须等到页面被渲染后,爬虫才能爬到。但有个风险就是,不一定页面上的内容全数都能被成功渲染,有可能因为检索预算不足的情况下渲染不到你的链接,所以务必留意链接的部分。
  (三)删除重复内容
  Google 倾向将重复页面删除,或者是降低重复页面的爬取优先级别。许多JavaScript 所产生的网页,都会有个app shell models,可以想像他是最小化的HTML、CSS 及JS 所组成,用户可以在不同需求下再次载入所需要的内容。
  但这有一个问题就是,app shell models 只有最简单少量的内容及源代码,所以很有可能被Google 误判为重复性内容,也造成其页面能够被渲染的优先级下降,正确的内容无法被索引,以及错误的页面被排名。
  (四)缓存及其它
  Google 下载页面HTML、CSS、JS 文档并渲染后,就会将其缓存。并且还有其它许多事情是Google 会同时处理的,并不止于这些,但处理页面的部分重点就在上述几项。
  Render queue (渲染序列)
  接下来许多页面即将被渲染, 所以在渲染排队中,根据Google 早期的说法,由于检索预算的优化,渲染页面并检索会是比较后期的事,俗称第二波索引( two waves of indexing ),但其实在近期onely 的Bartosz Goralewicz 与John 及Martin 讲述到,第二波索引的影响其实越来越小,Google 在等待渲染的中位数时间也只有5 秒钟,可见Google 在渲染并索引这一块下了相当大的功夫,未来渲染也将与检索能够同步进行‍。
  Renderer(渲染器)
  还记得前面说的食谱与料理吗?页面在渲染前的DOM 跟渲染后的DOM 就像料理的食谱,以及做好的烤鸡一样,简单讲DOM 就是像图中那树状图所呈现。
  料理前的食谱是不会改变的,所以渲染前的页面源代码一样不会因触发JavaScript 而改变,所以可以想像Renderer 就是一个主厨,料理食谱并且产生一道料理(JavaScript 渲染出来的页面),Renderer 为的就是去渲染出JavaScript 相关内容。
  要知道光是可以爬取整个网路世界成千上亿的资料便是不容易,还要将其内容渲染出来耗费资源非同小可,根据onely 指出,为了让JavaScript 内容被爬取、渲染并且索引,耗费的资源是一般HTML 页面的20 倍,一定要格外小心。让我们看看渲染器中有哪些重要的东西吧。
  (1)快取资源(Cache Resource)
  Google 相当重度依赖快取,它会快取各种文档,文档快取、页面快取、API requests 等,在被送到渲染器前就会先快取起来。因为不太可能每准备渲染一页,Google 就下载一次资源,所以优先快取好的文档资源就能快速渲染页面。
  但这也带来几个问题,有可能Google 会快取到旧的档案、旧版本的资源,导致在渲染页面时出现错误。如果有这种状况出现记得做好版本控制或是内容指纹,让Google 可以知道你更新了新的内容。
  (2)没有特定逾时时间(No Fixed Timeout)
  很多网上谣传渲染器只会用5 秒渲染你的页面,但其实并不然,Google 渲染时可能会加载原有快取的档案,会有5 秒的这一说法,主要是因为网址审查工具相关工具,检测页面时需要获取资源所以需要设立合理的逾时时间。
  为了确保内容完整呈现,Google 没有特地设定逾时时间,但为了爬虫爬取及访客体验,更快的速度一定是更好的。
  (3)渲染后,Google 看到了什么?
  这边要提到一个很重要的点是,Google 并不会主动与网页上的内容做互动,所以有些JavaScript 的特效,需要访客点击或触发的特效,是不会被Google 所触发,不会点击更不会滚动页面。
  所以早期你们一定有听过一个说法,不要使用瀑布流网页的原因就是如此,因为Google 不会卷动你页面的情况下,就无法触发JavaScript 所产生的内容,但Google 也不笨喔,为了克服瀑布流,他们直接把机器人设定成一台超长版手机,这样可以直接渲染出指定长度的内容。
  可是一般需要JavaScript 触发的内容无法被Google 渲染出来了喔,所以一定要特别注意,链接也不要出现JavaScript 所产生之链接。
  四、如何打造JavaScript 友善的网站
  前面我们说到JavaScript 现在越来越重要,也是越来越多网站使用的技术,所以与其完全避开使用JavaScript,不如打造一个既能满足开发者需求,又能争取排名的JavaScript 网站,让来看看有哪些重要因素吧。
  1.可被爬取(Crawlability):确保你的网站能保持良好的结构被爬取,并且爬虫也能找到有价值的内容。
  2.可被渲染(Renderability):确保页面上的内容可以被渲染。
  3.爬取预算(Crawl budget):Google 花了多少资源及时间渲染你的页面
  你的JavaScript 内容对搜索引擎足够友善吗?
  首先检查。你要知道你的网页在Google 眼中长的如何,那到底有哪些常见检查方法,这些方法正确吗?
  1.透过网址审查工具
  Google Search Console 的网站审查工具可以呈现渲染后的页面,其它官方的工具包含AMP 测试工具、富媒体搜索结果测试等官方检测工具,皆能呈现出渲染后的样貌,这边以移动友好测试工具为例。
  可以看到屏幕截图的画面,显示出Google 渲染出的画面,可以试着去看屏幕截图,重要内容是否能够被渲染出来。
  渲染后的屏幕画面
  另一方,你可以从检查工具的源代码中查看内容是否有被渲染出来,直接搜索内容、H 标签等方式确认。
  记得从渲染后的HTML(DOM – the rendered code)检查:
  2.site 指令+关键字检查
  site 指令一般而言,大多用来检查页面在Google 之收录状况,那如果说你直接『site:网址』后发现页面有被Google 收录,你就能用这个方法检查,因为Google 其实会根据关键字修改搜索结果页上的Description,所以当你输入一段内文时,Google 其实很有可能根据你这一段内文呈现在Description 上给你看。
  以pressplay 页面为例,pressplay 上的课程简介其实就是用JavaScript 去产生的,下图中可以看到,当我们将JavaScript 功能关闭时,就会发现内容只剩下下面那一段,那么要确认Google 是否有索引到主要内容便可用『site 指令+关键字』做检查。
  只有上面红框文字非JavaScript 产生。
  而在连老师『每月给你SEO最新趋势』这堂课中会发现,只要将JavaScript 功能关掉,主要内容便只剩下其中红框这一段,再来,复制一段JavaScript 产生内容的文字『每年服务客户横跨12大产业,我们了解你的产业问题,资深SEO专家团队陪你洞悉新·SEO』+ site:网址试试看。
  有没有发现,其实JavaScript 产生的内容Google 是有渲染出来并且索引到的,但如果要更准确的检查,建议还是要从官方的网址测试工具查看。
  注:网址审查工具:
  Google Search Console 网址审查工具#%E7%B6%B2%E5%9D%80%E5%AF%A9%E6%9F%A5
  结构化测试工具
  富媒体搜索结果测试工具
  AMP 测试工具
  移动友好检测工具
  Google 无法索引我的网页怎么办
  刚刚前面有提到,透过网址审查工具首先检查Google 渲染页面的状态为何,如果渲染未出现主要内容,那么就可能导致内容无法被索引,你需要透过网址审查工具中的更多信息,查看是否有资源遭到阻挡。
  更多信息中会告诉你哪些资源遭到封锁
  所以,先确保内容是否能被正确渲染后,再确保能否被索引,接着才能优化内容竞争排名。
  Google 未能索引你网页的原因:
  了解Google是否能渲染你的内容,是否能正确索引,然后再争取排名,一步步找出问题并解决它。
  五、渲染方式的不同:向Google 展示JavaScript 内容的不同方式
  你以为你的页面对Google 来说只是渲染出来,然后查看内容、收录并且排名吗?其实没那么简单,网页渲染的呈现方式还能分为客户端渲染(Client Side Rendering)、服务器端渲染(Server Side Rendering)、混合式渲染等方式。
  
  SSR(服务器端渲染),通常对于Google bot 以及访客而言,能够接受到完整的HTML 档案,内容也已经呈现好了。
  CSR(客户端渲染),近几年来越来越流行的渲染方式,对于Google bot 及访客而言,最初拿到的页面几乎是空白的HTML 档案,随着访客的操作,JavaScript 非同步的产生并下载内容。用料理与食谱来比喻,Google bot 及访客都只拿到了一份食谱,后面呈现端看访客如何烘培蛋糕(操作网站)。
  但是,Google bot 并不像访客一样,会有许多花里胡哨的操作,Google bot 不会滚动、不会点击更不会跟网站进行互动,所以如果你是全CSR(客户端渲染)的页面一定要注意,解决方法如下:
  ①服务器端渲染(SSR)
  敞偌你的页面因为JavaScript 渲染问题导致页面无法被索引,那强烈建议将重要页面或是网站改成服务器端渲染。
  ②动态渲染(Dynamic Rendering )
  有时候当然不可能说全改成SSR ,于是动态渲染就变成当今蛮重要的一种渲染方式,能同时做到CSR 想呈现的效果,又能同时达到SEO 排名。
  从下图可以看到,网页使用了全JavaScript 所产生的内容,但是提供给Google bot 的是另一静态HTML 页面,很好的解决了Google 爬虫无法查看渲染页面的问题。
  以下三种服务可以很好的帮助你实现动态渲染功能:
  Prerender.io
  Puppeteer
  Rendertron #0
  Google 官方文件也提供了转译原理、说明及方式,推荐大家看看。而下图是各种渲染JavaScript 的方法,其实大部分对于Google 来说都是渲染的出来的,比较难的还是在CSR(客户端渲染)的部分,所以如果你是CSR 建议导入动态渲染喔。
  六、如何建构一个友善SEO 的JavaScript 网站
  其实这个小节的内容有部分你可能过去就知道了,但因为JavaScript 的关系仍有部分不同。
  允许Google 爬取
  如果连网页都不能爬取、渲染的JavaScript 资源都无法读取的话,就不用说要排名啰,记得Robots.txt里不要禁止渲染相关资源,在Robots.txt中加入以下指令:
  User-Agent: Googlebot
  Allow: .js
  Allow: .css
  On-page 优化
  基本上on-page 上的重要元素应该都要能够被呈现出来,记得透过网址审查工具仔细检查是否都有出现:
  JavaScript 网站最常出现的一个状况是重复Title/Description 被重复使用,记得可以从Google Search Console 中的涵盖范围查看,又或者透过Screaming Frog 等工具确认。
  网址的点击
  前面虽然都有提到,但这边还是正式说明一下,在2018 年的Google I/O 大会上便说到,因为Googlebot 并不会去点击、滚动或是与网页做互动,所以如果你的链接是以onclick 的方式呈现的话,将不会被Googlebot 所爬取。
  对Google 而言,好链接与坏链接
  同样的,在导航上、分页上、内容上一样切记要使用 的方式去呈现链接,才能确保Google 会发现并爬取你的链接。
  网址的更新
  对于部分网页采用SPA(Single Page Application)方式所呈现的网页,在更新网页时,必须使用History API,对于较早期的开发者而言,在更新网页Url 时采用的是片段(fragement)的方式,那网址就会变成我们常见的锚点,如下:
  Our products
  但以『#』这种形式的连结对于Google 来说并不会抓取喔!虽然早期开发出一种连结形式,将『#』取代成『#!』,但这种方式已经过时了,网址也会变得相当丑。
  但是透过History API 的方式就能让网页资讯变动时,链接才会变换成Google 可爬取的形式,完整介绍可参考Google 官方文件。
  错误页面
  因为JavaScript 框架是客户端而非伺服务器端,所以像是当SPA 页面产生错误时,并没有办法传递出404 状态码到服务器中,此时请采取以下其中一种方式解决:
  l使用JavaScript 转移到你原本就设定好404 状态码及页面不存在讯息之页面
  l将错误页面加上noindex 标签,并在页面上呈现『404 页面错误』信息,这样子页面就能被视作软404(soft 404)的状态。
  Sitemap
  我们可能因为使用JavaScript 产生了网站的许多内容,并没有办法说一次到位,解决所有JavaScript 产生的SEO 问题,此时Sitemap.xml 有着重要的角色,就是告知Google 网站重要的页面有哪些,对于你提交的页面,Google 可能会优先爬取。
  但同时,你也必须确保Sitemap 上的所有页面链接没有以下问题:
  重复内容
  被canonical 指到别的页面
  404 错误页面
  301 转址到其它页面
  空白页面
  等等…
  这样Sitemap 才能真正的发挥他的作用,让Google 知道你重要的页面。
  总结
  JavaScript 所产生的内容,已经不像过往几年Google 爬虫完全无法理解,随着开发技术的进步JavaScript 也成为网页开发的重要元素,所以不要急着排斥它。
  记得首先,让Google 能够渲染出你的页面;其次,确认Google 有顺利索引你的页面;接着,按着你一般优化SEO 的方式,排除重复内容、优化内容,加强关键字排名。
  这看似简单的几个步骤就花了很大一个篇幅在说明了,所以一起努力建立一个友善SEO 的JavaScript 网站吧!
  参考资料:
  l了解JavaScript 搜寻引擎最佳化(SEO) 基础知识
  l修正会影响搜寻体验的JavaScript 问题
  l导入动态转译
  lRendering on the Web
  lJavaScript SEO: What You Need to Know
  lThe Ultimate Guide to JavaScript SEO (2020 Edition)
  lJavaScript and SEO: The Difference Between Crawling and Indexing
  lMaking JavaScript and Google Search work together
  lRendering SEO manifesto – why JavaScript SEO is not enough
  lJavaScript vs. Crawl Budget: Ready Player One
  lEverything You Know About JavaScript Indexing is Wrong
  lStatic vs. Server Rendering
  lDeliver search-friendly JavaScript-powered websites (Google I/O '18)
  lJavaScript SEO – How Does Google Crawl JavaScript 查看全部

  js提取指定网站内容 JavaScript SEO 终极指南(Google SEOer必看)
  5.分类筛选器
  所以,如果这些内容在JavaScript 上没有处理好的话,很容易造成索引及排名上遇到困难。
  那如何检查网页上哪些内容是JavaScript 所产生的呢
  一、通过使用Chrome 插件:
  这边介绍的工具叫做『Quick Javascript Switcher』,这个插件可以直接开关网页的JavaScript 功能,只要你关掉JavaScript 后,发现哪个部分的内容不见了,那很大程度就是那个内容是JavaScript 所产生。
  从下图可以看到,当我们用插件关掉JavaScript 功能后,Pressplay 的主要内容消失不见了,那就代表说其中主要内容由JavaScript 所产生。
  二、从开发者工具关闭
  首先点击鼠标右键找到『检查』,你会进入开发者介面。
  接着使用快捷键『Control + Shift + p』 (Windows) 或是『Command + Option + p』 (Mac)。
  接着在光标处中输入JavaScript,就会看到一个『Disable JavaScript』选项,点击即可关闭JavaScript,同理要再打开只需使用相同方法再点击一次便可打开JavaScript 功能。
  为什么网页源代码没有JavaScript 产生的内容!?
  一般来说,我们在检查网页中的meta 标签、H 标签等内容时,最常做的就是从网页源代码中去查看,也就是『右键> 检查网页源代码』所呈现的内容。
  而这个文件就是HTML 文件,但这份HTML 文件仅仅代表浏览器在解析页面时的最初讯息,而JavaScript 所产生的内容并不在一开始的HTML 文件上。
  所以,检查网页源代码无法知道JavaScript 更新后的动态内容。
  此时就要介绍一下HTML 加工后的DOM 了,这边为了不复杂化,简单叙述一下,当你『右键> 检查』出来的东西便是加工过的DOM(如下图)。DOM 里面会随着你与网站的互动,将JavaScript 所产生的内容加上去。
  那如何区分HTML 源代码还是加工后的DOM 呢?
  PS: 如果Google 爬取页面时无法完整呈现JavaScript 产生的页面,它至少可以索引为加载过的HTML 原始码。
  在确认并且知道哪些内容属于JavaScript 所产生的之后,再就是理解Google 怎么爬取JavaScript,并且优化你的内容让网页排名上升。
  二、Google 怎么爬取JS 网站
  对于搜索引擎而言,JavaScript 一直是Google 努力在改善爬虫技术,让搜索引擎索引并排名的目标之一。虽然JavaScript 为访客带来更良好的使用体验,但是对于搜索引擎而言却不是一件容易的事情,请记得:
  根据onely 网站调查指出,许多大品牌网页上JavaScript 之内容未被索引的情况:
  你可以想像,Yoox 在国外是知名电商网站,每个月可以有高达1400 万的流量,但是网站由JavaScript 产生的内容竟然由高达92% 是Google 不会索引到的,由此可知这样对SEO 的影响可以有多大,损失又可以有多多。
  但同样的,也有把JavaScript 所产生的内容处理的很好的网站, 以及 的网站分别让JavaScript 所产生的内容,被100% 及99% 的索引了,所以,只要方法得当,我们也能让JavaScript 与SEO 兼顾。
  Google 爬取页面的过程
  在早期搜索引擎只需要下载HTML 档便可完整了解网页内容,但由于JavaScript 技术的崛起及普及,搜索引擎甚至需要像浏览器一样,以便他们以访客的角度查看网页内容。
  而Google 处理渲染的系统,被称为Web Rendering Service (WRS),中文可以翻译成网页渲染器,后面以WRS 代称,而Google 也给出了一张简化的图作为说明。
  简单说明Google 爬取步骤,传统爬取HTML 档页面时,每项元素都很好爬取,整个索引并排名页面的过程也迅速:
  1.Google bot 下载HTML 档
  2.Google bot 从源代码中提取url 网址,并快速访问这些url
  3.Google bot 下载CSS 档案
  4.Google bot 将下载下来的资源送到Google 的Indexer
  5.Google 的Indexer 检索页面
  但如果是今天爬取JavaScript 所产生的网站内容的话,Google 会怎么爬取呢:
  1.Google bot 下载HTML 档
  2.Google bot 在源代码中找不到链接,因为JavaScript 未被执行
  3.Google bot 下载CSS 及JavaScript 档案
  4.Google bot 使用WRS(渲染器,Indexer 的一部分)解析、编译并执行JavaScript
  5.WRS 从外部API、资料库获取资料(data)
  6.Indexer 可以索引内容
  7.Google 发现新的链接,并将其加入爬取排队队伍之中(Googlebot's crawling queue)。至此,执行一般Google bot 爬取HTML 页面的第二步。
  可以发现,为了渲染出页面,Google 多了许多步骤。再来讲一下渲染过程中,Crawler、Processing、Renderer 及Index 之重要节点。
  三、Google 爬取JavaScript 过程中的重要节点
  Crawler(爬虫)
  首先,crawler 会先向网站服务器发送一段请求(request),网站服务器会返回内容及其标头(header),然后crawler 将它储存起来。
  而由于mobile-first indexing的关系,发送请求的可能大多都是来自手机版的爬虫(mobile user-agent),从Google Search Console上可以检查到,你可以透过网址审查或是涵盖范围来知道现在是电脑版索引还是手机版优先索引的状态。
  然后有些网站会使用user-agent detection,侦测访客来到自己网站时,是用手机还是桌机、浏览器是什么、浏览器版本的不同资讯,再根据这些资讯给访客相对应的资讯,例如今天侦测到访客是用手机版本的chrome,便呈现手机版的页面给访客看。
  需要注意的是,有些网站遇到爬虫时可能会设定禁止该爬虫爬取页面,或是禁止特定地区ip 的访客查看页面,这时候就要小心如果网页没设定好的话,很有可能爬虫是看不到你的内容的喔。
  记得从几个方面测试看看Google 爬虫能否顺利看到你的页面:Google Search Console 的网址检查器、移动友好测试工具以及富媒体结果测试工具。
  补充:从爬取过程那张图可以看到,Google 将爬取后产生的页面称之为HTML,但实际上,为了建构页面内容,Google 其实爬取并储存了相关所需的资源,像是CSS 文档、JS 文档、API 端口、XHR requests等相关资源。
  Processing(处理)
  Processing 的过程中其实是非常复杂且处理很多事的,这边重点讲述Google 处理JavaScript 的过程。
  (一)遵循限制性最高的要求
  什么是限制性最高的要求,就是假设今天Google 渲染(render)出页面后,原本meta robots 的信息是index 被加入了noindex,那么Google 将不会索引其页面,甚至其它尚未被渲染的页面,因为JS 产生noindex 这类的语法,则可能导致页面无法被渲染。
  (二)处理资源及链接
  Google 并不像访客那样浏览页面,Processing 的过程中有个很重要的工作便是检查页面上的链接以及建构该页面所需的文档。
  这些链接被记录,加到等待爬取的排队序列中(crawl queue),反覆执行找链接、链接排队、爬取链接,便是Google 本身爬取整个网路世界的方式。
  Google 透过属性,将建构页面所需的资源,像是JS、CSS 文档被记录。但是页面对页面的链接需要以特定的形式所呈现,才能被Google 所抓取,那就是以链接”>的形式。
  
  能被爬取的連結a>
  不能被爬取的連結span>
  不能被爬取的連結a>
  能被爬取的連結a>
  如果你的链接是JavaScript 所产生的话,那必须等到页面被渲染后,爬虫才能爬到。但有个风险就是,不一定页面上的内容全数都能被成功渲染,有可能因为检索预算不足的情况下渲染不到你的链接,所以务必留意链接的部分。
  (三)删除重复内容
  Google 倾向将重复页面删除,或者是降低重复页面的爬取优先级别。许多JavaScript 所产生的网页,都会有个app shell models,可以想像他是最小化的HTML、CSS 及JS 所组成,用户可以在不同需求下再次载入所需要的内容。
  但这有一个问题就是,app shell models 只有最简单少量的内容及源代码,所以很有可能被Google 误判为重复性内容,也造成其页面能够被渲染的优先级下降,正确的内容无法被索引,以及错误的页面被排名。
  (四)缓存及其它
  Google 下载页面HTML、CSS、JS 文档并渲染后,就会将其缓存。并且还有其它许多事情是Google 会同时处理的,并不止于这些,但处理页面的部分重点就在上述几项。
  Render queue (渲染序列)
  接下来许多页面即将被渲染, 所以在渲染排队中,根据Google 早期的说法,由于检索预算的优化,渲染页面并检索会是比较后期的事,俗称第二波索引( two waves of indexing ),但其实在近期onely 的Bartosz Goralewicz 与John 及Martin 讲述到,第二波索引的影响其实越来越小,Google 在等待渲染的中位数时间也只有5 秒钟,可见Google 在渲染并索引这一块下了相当大的功夫,未来渲染也将与检索能够同步进行‍。
  Renderer(渲染器)
  还记得前面说的食谱与料理吗?页面在渲染前的DOM 跟渲染后的DOM 就像料理的食谱,以及做好的烤鸡一样,简单讲DOM 就是像图中那树状图所呈现。
  料理前的食谱是不会改变的,所以渲染前的页面源代码一样不会因触发JavaScript 而改变,所以可以想像Renderer 就是一个主厨,料理食谱并且产生一道料理(JavaScript 渲染出来的页面),Renderer 为的就是去渲染出JavaScript 相关内容。
  要知道光是可以爬取整个网路世界成千上亿的资料便是不容易,还要将其内容渲染出来耗费资源非同小可,根据onely 指出,为了让JavaScript 内容被爬取、渲染并且索引,耗费的资源是一般HTML 页面的20 倍,一定要格外小心。让我们看看渲染器中有哪些重要的东西吧。
  (1)快取资源(Cache Resource)
  Google 相当重度依赖快取,它会快取各种文档,文档快取、页面快取、API requests 等,在被送到渲染器前就会先快取起来。因为不太可能每准备渲染一页,Google 就下载一次资源,所以优先快取好的文档资源就能快速渲染页面。
  但这也带来几个问题,有可能Google 会快取到旧的档案、旧版本的资源,导致在渲染页面时出现错误。如果有这种状况出现记得做好版本控制或是内容指纹,让Google 可以知道你更新了新的内容。
  (2)没有特定逾时时间(No Fixed Timeout)
  很多网上谣传渲染器只会用5 秒渲染你的页面,但其实并不然,Google 渲染时可能会加载原有快取的档案,会有5 秒的这一说法,主要是因为网址审查工具相关工具,检测页面时需要获取资源所以需要设立合理的逾时时间。
  为了确保内容完整呈现,Google 没有特地设定逾时时间,但为了爬虫爬取及访客体验,更快的速度一定是更好的。
  (3)渲染后,Google 看到了什么?
  这边要提到一个很重要的点是,Google 并不会主动与网页上的内容做互动,所以有些JavaScript 的特效,需要访客点击或触发的特效,是不会被Google 所触发,不会点击更不会滚动页面。
  所以早期你们一定有听过一个说法,不要使用瀑布流网页的原因就是如此,因为Google 不会卷动你页面的情况下,就无法触发JavaScript 所产生的内容,但Google 也不笨喔,为了克服瀑布流,他们直接把机器人设定成一台超长版手机,这样可以直接渲染出指定长度的内容。
  可是一般需要JavaScript 触发的内容无法被Google 渲染出来了喔,所以一定要特别注意,链接也不要出现JavaScript 所产生之链接。
  四、如何打造JavaScript 友善的网站
  前面我们说到JavaScript 现在越来越重要,也是越来越多网站使用的技术,所以与其完全避开使用JavaScript,不如打造一个既能满足开发者需求,又能争取排名的JavaScript 网站,让来看看有哪些重要因素吧。
  1.可被爬取(Crawlability):确保你的网站能保持良好的结构被爬取,并且爬虫也能找到有价值的内容。
  2.可被渲染(Renderability):确保页面上的内容可以被渲染。
  3.爬取预算(Crawl budget):Google 花了多少资源及时间渲染你的页面
  你的JavaScript 内容对搜索引擎足够友善吗?
  首先检查。你要知道你的网页在Google 眼中长的如何,那到底有哪些常见检查方法,这些方法正确吗?
  1.透过网址审查工具
  Google Search Console 的网站审查工具可以呈现渲染后的页面,其它官方的工具包含AMP 测试工具、富媒体搜索结果测试等官方检测工具,皆能呈现出渲染后的样貌,这边以移动友好测试工具为例。
  可以看到屏幕截图的画面,显示出Google 渲染出的画面,可以试着去看屏幕截图,重要内容是否能够被渲染出来。
  渲染后的屏幕画面
  另一方,你可以从检查工具的源代码中查看内容是否有被渲染出来,直接搜索内容、H 标签等方式确认。
  记得从渲染后的HTML(DOM – the rendered code)检查:
  2.site 指令+关键字检查
  site 指令一般而言,大多用来检查页面在Google 之收录状况,那如果说你直接『site:网址』后发现页面有被Google 收录,你就能用这个方法检查,因为Google 其实会根据关键字修改搜索结果页上的Description,所以当你输入一段内文时,Google 其实很有可能根据你这一段内文呈现在Description 上给你看。
  以pressplay 页面为例,pressplay 上的课程简介其实就是用JavaScript 去产生的,下图中可以看到,当我们将JavaScript 功能关闭时,就会发现内容只剩下下面那一段,那么要确认Google 是否有索引到主要内容便可用『site 指令+关键字』做检查。
  只有上面红框文字非JavaScript 产生。
  而在连老师『每月给你SEO最新趋势』这堂课中会发现,只要将JavaScript 功能关掉,主要内容便只剩下其中红框这一段,再来,复制一段JavaScript 产生内容的文字『每年服务客户横跨12大产业,我们了解你的产业问题,资深SEO专家团队陪你洞悉新·SEO』+ site:网址试试看。
  有没有发现,其实JavaScript 产生的内容Google 是有渲染出来并且索引到的,但如果要更准确的检查,建议还是要从官方的网址测试工具查看。
  注:网址审查工具:
  Google Search Console 网址审查工具#%E7%B6%B2%E5%9D%80%E5%AF%A9%E6%9F%A5
  结构化测试工具
  富媒体搜索结果测试工具
  AMP 测试工具
  移动友好检测工具
  Google 无法索引我的网页怎么办
  刚刚前面有提到,透过网址审查工具首先检查Google 渲染页面的状态为何,如果渲染未出现主要内容,那么就可能导致内容无法被索引,你需要透过网址审查工具中的更多信息,查看是否有资源遭到阻挡。
  更多信息中会告诉你哪些资源遭到封锁
  所以,先确保内容是否能被正确渲染后,再确保能否被索引,接着才能优化内容竞争排名。
  Google 未能索引你网页的原因:
  了解Google是否能渲染你的内容,是否能正确索引,然后再争取排名,一步步找出问题并解决它。
  五、渲染方式的不同:向Google 展示JavaScript 内容的不同方式
  你以为你的页面对Google 来说只是渲染出来,然后查看内容、收录并且排名吗?其实没那么简单,网页渲染的呈现方式还能分为客户端渲染(Client Side Rendering)、服务器端渲染(Server Side Rendering)、混合式渲染等方式。
  
  SSR(服务器端渲染),通常对于Google bot 以及访客而言,能够接受到完整的HTML 档案,内容也已经呈现好了。
  CSR(客户端渲染),近几年来越来越流行的渲染方式,对于Google bot 及访客而言,最初拿到的页面几乎是空白的HTML 档案,随着访客的操作,JavaScript 非同步的产生并下载内容。用料理与食谱来比喻,Google bot 及访客都只拿到了一份食谱,后面呈现端看访客如何烘培蛋糕(操作网站)。
  但是,Google bot 并不像访客一样,会有许多花里胡哨的操作,Google bot 不会滚动、不会点击更不会跟网站进行互动,所以如果你是全CSR(客户端渲染)的页面一定要注意,解决方法如下:
  ①服务器端渲染(SSR)
  敞偌你的页面因为JavaScript 渲染问题导致页面无法被索引,那强烈建议将重要页面或是网站改成服务器端渲染。
  ②动态渲染(Dynamic Rendering )
  有时候当然不可能说全改成SSR ,于是动态渲染就变成当今蛮重要的一种渲染方式,能同时做到CSR 想呈现的效果,又能同时达到SEO 排名。
  从下图可以看到,网页使用了全JavaScript 所产生的内容,但是提供给Google bot 的是另一静态HTML 页面,很好的解决了Google 爬虫无法查看渲染页面的问题。
  以下三种服务可以很好的帮助你实现动态渲染功能:
  Prerender.io
  Puppeteer
  Rendertron #0
  Google 官方文件也提供了转译原理、说明及方式,推荐大家看看。而下图是各种渲染JavaScript 的方法,其实大部分对于Google 来说都是渲染的出来的,比较难的还是在CSR(客户端渲染)的部分,所以如果你是CSR 建议导入动态渲染喔。
  六、如何建构一个友善SEO 的JavaScript 网站
  其实这个小节的内容有部分你可能过去就知道了,但因为JavaScript 的关系仍有部分不同。
  允许Google 爬取
  如果连网页都不能爬取、渲染的JavaScript 资源都无法读取的话,就不用说要排名啰,记得Robots.txt里不要禁止渲染相关资源,在Robots.txt中加入以下指令:
  User-Agent: Googlebot
  Allow: .js
  Allow: .css
  On-page 优化
  基本上on-page 上的重要元素应该都要能够被呈现出来,记得透过网址审查工具仔细检查是否都有出现:
  JavaScript 网站最常出现的一个状况是重复Title/Description 被重复使用,记得可以从Google Search Console 中的涵盖范围查看,又或者透过Screaming Frog 等工具确认。
  网址的点击
  前面虽然都有提到,但这边还是正式说明一下,在2018 年的Google I/O 大会上便说到,因为Googlebot 并不会去点击、滚动或是与网页做互动,所以如果你的链接是以onclick 的方式呈现的话,将不会被Googlebot 所爬取。
  对Google 而言,好链接与坏链接
  同样的,在导航上、分页上、内容上一样切记要使用 的方式去呈现链接,才能确保Google 会发现并爬取你的链接。
  网址的更新
  对于部分网页采用SPA(Single Page Application)方式所呈现的网页,在更新网页时,必须使用History API,对于较早期的开发者而言,在更新网页Url 时采用的是片段(fragement)的方式,那网址就会变成我们常见的锚点,如下:
  Our products
  但以『#』这种形式的连结对于Google 来说并不会抓取喔!虽然早期开发出一种连结形式,将『#』取代成『#!』,但这种方式已经过时了,网址也会变得相当丑。
  但是透过History API 的方式就能让网页资讯变动时,链接才会变换成Google 可爬取的形式,完整介绍可参考Google 官方文件。
  错误页面
  因为JavaScript 框架是客户端而非伺服务器端,所以像是当SPA 页面产生错误时,并没有办法传递出404 状态码到服务器中,此时请采取以下其中一种方式解决:
  l使用JavaScript 转移到你原本就设定好404 状态码及页面不存在讯息之页面
  l将错误页面加上noindex 标签,并在页面上呈现『404 页面错误』信息,这样子页面就能被视作软404(soft 404)的状态。
  Sitemap
  我们可能因为使用JavaScript 产生了网站的许多内容,并没有办法说一次到位,解决所有JavaScript 产生的SEO 问题,此时Sitemap.xml 有着重要的角色,就是告知Google 网站重要的页面有哪些,对于你提交的页面,Google 可能会优先爬取。
  但同时,你也必须确保Sitemap 上的所有页面链接没有以下问题:
  重复内容
  被canonical 指到别的页面
  404 错误页面
  301 转址到其它页面
  空白页面
  等等…
  这样Sitemap 才能真正的发挥他的作用,让Google 知道你重要的页面。
  总结
  JavaScript 所产生的内容,已经不像过往几年Google 爬虫完全无法理解,随着开发技术的进步JavaScript 也成为网页开发的重要元素,所以不要急着排斥它。
  记得首先,让Google 能够渲染出你的页面;其次,确认Google 有顺利索引你的页面;接着,按着你一般优化SEO 的方式,排除重复内容、优化内容,加强关键字排名。
  这看似简单的几个步骤就花了很大一个篇幅在说明了,所以一起努力建立一个友善SEO 的JavaScript 网站吧!
  参考资料:
  l了解JavaScript 搜寻引擎最佳化(SEO) 基础知识
  l修正会影响搜寻体验的JavaScript 问题
  l导入动态转译
  lRendering on the Web
  lJavaScript SEO: What You Need to Know
  lThe Ultimate Guide to JavaScript SEO (2020 Edition)
  lJavaScript and SEO: The Difference Between Crawling and Indexing
  lMaking JavaScript and Google Search work together
  lRendering SEO manifesto – why JavaScript SEO is not enough
  lJavaScript vs. Crawl Budget: Ready Player One
  lEverything You Know About JavaScript Indexing is Wrong
  lStatic vs. Server Rendering
  lDeliver search-friendly JavaScript-powered websites (Google I/O '18)
  lJavaScript SEO – How Does Google Crawl JavaScript

js提取指定网站内容 真香系列-JSFinder实用改造

网站优化优采云 发表了文章 • 0 个评论 • 85 次浏览 • 2022-06-28 14:27 • 来自相关话题

  js提取指定网站内容 真香系列-JSFinder实用改造
  点击上方蓝字关注我吧!
  1.前言
  JSFinder是一款优秀的github开源工具,这款工具功能就是查找隐藏在js文件中的api接口和敏感目录,以及一些子域名。
  github链接:https://github.com/Threezh1/JSFinder
  用于提取的正则表达式参考了LinkFinder
  SFinder获取URL和子域名的方式:
  一些简单的使用方式:
  简单爬取
  python JSFinder.py -u http://www.mi.com<br />#这个命令会爬取 http://www.mi.com 这单个页面的所有的js链接,并在其中发现url和子域名
  深度爬取
  python JSFinder.py -u http://www.mi.com -d<br />#深入一层页面爬取JS,时间会消耗的更长,建议使用-ou 和 -os来指定保存URL和子域名的文件名python JSFinder.py -u http://www.mi.com -d -ou mi_url.txt -os mi_subdomain.txt
  批量指定URL/指定JS
  指定URL:
  python JSFinder.py -f text.txt
  指定JS:
  
  python JSFinder.py -f text.txt -j
  可以用brupsuite爬取网站后提取出URL或者JS链接,保存到txt文件中,一行一个。
  指定URL或JS就不需要加深度爬取,单个页面即可,等等,这可以去github上面看使用说明。
  2.改造
  2.1 为什么要改造这个东西?
  因为我经常使用这款工具,我发现了很多不足之处,比如说,如果爬取一个大型一点的,会发现很多url,接口,但是大多数都是404,没有用处的,就是通过人工去筛选就得费好长一段时间,我有一次爬下来了1200多条,密密麻麻............................
  所有我的设想是可以增加一个验证模块,进行简单的验证,扔掉那些不存在的url链接,减少人工的筛选。
  2.2 找到源码一顿改(验证模块)
  改源码一定要找到关键点改,我这里直接在它进行数据处理的时候加入我想要的东西:
   thread_num = 0 info = '访问成功' lock = threading.Lock() if urls == None: return None find_url_all_num = len(urls) content_url = "" content_subdomain = "" if self.args.verify !=0: print("A total of Find " + str(len(urls)) + " URL:\n") print("-----------------------But further validation is needed-----------------!\n\n\n") domian_text = requests.get(domian,verify =False).text print("The length of the page currently visited =>"+str(len(domian_text))) result ={} for url in urls: thread_num += 1 self.therads_op(url, content_url, lock,thread_num,result) if thread_num == 100: time.sleep(1) find_url_success_num = 0 for length,url_list in result.items(): print("-----------------------The return packet length is :{len}------------------------".format(len =length)) for url in url_list: print(url+"\n") find_url_success_num += 1 content_url+=url+"\n"
  关键的一些代码,这里因为使用了网络验证,所以写了个多线程:
   def therads_op(self,url,content_url,lock,thread_num,result): threading.Thread(target=self.request(url,content_url,lock,result),args=(url,content_url,lock,result,)) if lock.acquire(): thread_num -= 1 lock.release()
  验证模块:
  def request(self,url,content_url,lock,result): headers = { "User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", } try: resp = requests.get(url,verify = False,timeout = 10,headers=headers) if resp.status_code != 404 and lock.acquire(): content_url += url + "\n" if result.get(str(len(resp.text)), 0) == 0: result[str(len(resp.text))] = [] result[str(len(resp.text))].append(url) else: result[str(len(resp.text))].append(url) lock.release()<br /> except Exception as e: pass finally: try: lock.release() except RuntimeError as e: pass
  这里我是直接判断它返回值是不是404,当然你也可以加入你自己的判断条件,可以看到我的源码里,有计数返回包的长度,因为我发现很多包的返回包都是一样的,所以我这里判断长度,进行归类,有利于我们自己人工筛选,我们只需要得到任意长度的一个url返回包,就可以知道其他有着相同长度的url返回的内容(这就是我当时的想法吧)
  2.3 找到源码一阵改(输出数据格式)
  因为原工具是有把输出结果输出到一个文件的功能,但是我感觉不够直观,所以我把输出结果转换成了html文件,可以直接点击url,进行访问,方便了很多。
  if self.args.output_html !=None: table_tr0 = '' html = html_Template() total_str = '共url: %s,访问成功:%s,失败 %s' % (find_url_all_num, find_url_success_num, find_url_all_num-find_url_success_num) if self.args.verify !=0: for length,url_list in result.items(): for url in url_list: url_a = "<a href={url}>点击</a>".format(url=url) table_td = html.TABLE_TMPL % dict(length=length, url=url, result=info, ask_url=url_a, ) table_tr0 += table_td else: for url in urls: url_a = "<a href={url}>点击</a>".format(url=url) table_td = html.TABLE_TMPL % dict(length="无法获取", url=url, result=info, ask_url=url_a, ) table_tr0 += table_td output = html.HTML_TMPL % dict(domain=self.args.url,value=total_str, table_tr=table_tr0, ) # 生成html报告 filename = '{date}_{url}.html'.format(date=time.strftime('%Y%m%d%H%M%S'),url = self.args.output_html) dir = str(os.getcwd()) filename = os.path.join(dir, filename) with open(filename, 'wb') as f: f.write(bytes(output, "utf-8"))
  
  我把源码改成了一个类的形式,有利于以后的加入到大项目中,积小成多!
  2.4 效果预览
  在没有加验证参数的情况下:
  开启验证的情况下:
  3.总结
  本来还想加一个爬虫模块进去的,但是作者有自己的爬虫模块,就算了,如果可以的话,也可以把一些优秀的开源爬虫加进去,就真的很nice了,我以后再加把,先这样吧,运行有什么问题可以及时联系我,越改越实用。
  挺香的!真香,找个机会把源码放到github上面去:
  exe程序百度云链接:
  链接:https://pan.baidu.com/s/17WIa94fr5EAHgfo4UI6Eyw 提取码:qq0c 复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V3的分享
  END
  看完记得点赞,关注哟,爱您!
  请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付! 查看全部

  js提取指定网站内容 真香系列-JSFinder实用改造
  点击上方蓝字关注我吧!
  1.前言
  JSFinder是一款优秀的github开源工具,这款工具功能就是查找隐藏在js文件中的api接口和敏感目录,以及一些子域名。
  github链接:https://github.com/Threezh1/JSFinder
  用于提取的正则表达式参考了LinkFinder
  SFinder获取URL和子域名的方式:
  一些简单的使用方式:
  简单爬取
  python JSFinder.py -u http://www.mi.com<br />#这个命令会爬取 http://www.mi.com 这单个页面的所有的js链接,并在其中发现url和子域名
  深度爬取
  python JSFinder.py -u http://www.mi.com -d<br />#深入一层页面爬取JS,时间会消耗的更长,建议使用-ou 和 -os来指定保存URL和子域名的文件名python JSFinder.py -u http://www.mi.com -d -ou mi_url.txt -os mi_subdomain.txt
  批量指定URL/指定JS
  指定URL:
  python JSFinder.py -f text.txt
  指定JS:
  
  python JSFinder.py -f text.txt -j
  可以用brupsuite爬取网站后提取出URL或者JS链接,保存到txt文件中,一行一个。
  指定URL或JS就不需要加深度爬取,单个页面即可,等等,这可以去github上面看使用说明。
  2.改造
  2.1 为什么要改造这个东西?
  因为我经常使用这款工具,我发现了很多不足之处,比如说,如果爬取一个大型一点的,会发现很多url,接口,但是大多数都是404,没有用处的,就是通过人工去筛选就得费好长一段时间,我有一次爬下来了1200多条,密密麻麻............................
  所有我的设想是可以增加一个验证模块,进行简单的验证,扔掉那些不存在的url链接,减少人工的筛选。
  2.2 找到源码一顿改(验证模块)
  改源码一定要找到关键点改,我这里直接在它进行数据处理的时候加入我想要的东西:
   thread_num = 0 info = '访问成功' lock = threading.Lock() if urls == None: return None find_url_all_num = len(urls) content_url = "" content_subdomain = "" if self.args.verify !=0: print("A total of Find " + str(len(urls)) + " URL:\n") print("-----------------------But further validation is needed-----------------!\n\n\n") domian_text = requests.get(domian,verify =False).text print("The length of the page currently visited =>"+str(len(domian_text))) result ={} for url in urls: thread_num += 1 self.therads_op(url, content_url, lock,thread_num,result) if thread_num == 100: time.sleep(1) find_url_success_num = 0 for length,url_list in result.items(): print("-----------------------The return packet length is :{len}------------------------".format(len =length)) for url in url_list: print(url+"\n") find_url_success_num += 1 content_url+=url+"\n"
  关键的一些代码,这里因为使用了网络验证,所以写了个多线程:
   def therads_op(self,url,content_url,lock,thread_num,result): threading.Thread(target=self.request(url,content_url,lock,result),args=(url,content_url,lock,result,)) if lock.acquire(): thread_num -= 1 lock.release()
  验证模块:
  def request(self,url,content_url,lock,result): headers = { "User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", } try: resp = requests.get(url,verify = False,timeout = 10,headers=headers) if resp.status_code != 404 and lock.acquire(): content_url += url + "\n" if result.get(str(len(resp.text)), 0) == 0: result[str(len(resp.text))] = [] result[str(len(resp.text))].append(url) else: result[str(len(resp.text))].append(url) lock.release()<br /> except Exception as e: pass finally: try: lock.release() except RuntimeError as e: pass
  这里我是直接判断它返回值是不是404,当然你也可以加入你自己的判断条件,可以看到我的源码里,有计数返回包的长度,因为我发现很多包的返回包都是一样的,所以我这里判断长度,进行归类,有利于我们自己人工筛选,我们只需要得到任意长度的一个url返回包,就可以知道其他有着相同长度的url返回的内容(这就是我当时的想法吧)
  2.3 找到源码一阵改(输出数据格式)
  因为原工具是有把输出结果输出到一个文件的功能,但是我感觉不够直观,所以我把输出结果转换成了html文件,可以直接点击url,进行访问,方便了很多。
  if self.args.output_html !=None: table_tr0 = '' html = html_Template() total_str = '共url: %s,访问成功:%s,失败 %s' % (find_url_all_num, find_url_success_num, find_url_all_num-find_url_success_num) if self.args.verify !=0: for length,url_list in result.items(): for url in url_list: url_a = "<a href={url}>点击</a>".format(url=url) table_td = html.TABLE_TMPL % dict(length=length, url=url, result=info, ask_url=url_a, ) table_tr0 += table_td else: for url in urls: url_a = "<a href={url}>点击</a>".format(url=url) table_td = html.TABLE_TMPL % dict(length="无法获取", url=url, result=info, ask_url=url_a, ) table_tr0 += table_td output = html.HTML_TMPL % dict(domain=self.args.url,value=total_str, table_tr=table_tr0, ) # 生成html报告 filename = '{date}_{url}.html'.format(date=time.strftime('%Y%m%d%H%M%S'),url = self.args.output_html) dir = str(os.getcwd()) filename = os.path.join(dir, filename) with open(filename, 'wb') as f: f.write(bytes(output, "utf-8"))
  
  我把源码改成了一个类的形式,有利于以后的加入到大项目中,积小成多!
  2.4 效果预览
  在没有加验证参数的情况下:
  开启验证的情况下:
  3.总结
  本来还想加一个爬虫模块进去的,但是作者有自己的爬虫模块,就算了,如果可以的话,也可以把一些优秀的开源爬虫加进去,就真的很nice了,我以后再加把,先这样吧,运行有什么问题可以及时联系我,越改越实用。
  挺香的!真香,找个机会把源码放到github上面去:
  exe程序百度云链接:
  链接:https://pan.baidu.com/s/17WIa94fr5EAHgfo4UI6Eyw 提取码:qq0c 复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V3的分享
  END
  看完记得点赞,关注哟,爱您!
  请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付!

JS逆向:滑块验证码加密分析

网站优化优采云 发表了文章 • 0 个评论 • 315 次浏览 • 2022-06-23 11:36 • 来自相关话题

  JS逆向:滑块验证码加密分析
  为什么要做逆向?动态网页爬虫一般可分为两种:Selenium爬取和接口爬取。
  两种方式各有优缺点:
  前者我们己经介绍了selenium的使用和验证码、滑块的使用,其虽然可以很好地处理网页异步加载问题,但面对大型爬虫任务时,效率还是比较低的;
  后者虽然爬取速度较快,但请求参数很可能是动态变化的,这时就需要利用一些前端的知识,重新构造参数,整个过程通常称为JS逆向。
  先来看一下简单的请求:
  
  但是往往在我们编写爬虫时,可能会碰到以下两种问题:造成这种问题原因是,你所正在爬取的页面采取了动态加载的方式动态加载网页其显示的页面则是经过Javascript处理数据后生成的结果,可以发生改变。
  JavaScript是一种运行在浏览器中的解释型编程语言,JavaScript非常值得学习,它既适合作为学习编程的入门语言,也适合当作日常开发的工作语言。
  JavaScript可以收集用户的跟踪数据,不需要重载页面即可直接提交表单,可在页面中嵌入多媒体文件,甚至可以运行网页游戏等。在很多看起来非常简单的页面背后通常使用了许多JavaScript文件。比如:
  
  这些数据的来源有多种,可能是经过Javascript计算生成的,也可能是通过Ajax加载的。Ajax = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),其最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页的内容。
  逆向工程
  对于动态加载的网页,我们想要获取其网页数据,需要了解网页是如何加载数据的,该过程就被成为逆向工程。
  对于使用了Ajax 请求技术的网页,我们可以找到Ajax请求的具体链接,直接得到Ajax请求得到的数据。
  需要注意的是,构造Ajax请求有两种方式:
  原生的Ajax请求,会直接创建一个XMLHTTPRequest对象。
  调用jQuery的ajax()方法。一般情况下,.ajax()会返回其创建的XMLHTTPRequest对象;但是,如果.ajax()的dataType参数指定了为script或jsonp类型,.ajax()不再返回其创建的XMLHTTPRequest对象。
  JQuery补充:
  在大型互联网公司的不断推广下,JavaScript生态圈也在不断的完善,各种类库、API接口层出不穷。
  jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“Write Less,Do More”,即倡导写更少的代码,做更多的事情。
  对于这两种方式,只要创建返回了XMLHTTPRequest对象,就可以通过Chrome浏览器的调试工具在NetWork窗口通过设置XHR过滤条件,直接筛选出Ajax请求的链接;如果是$.ajax()并且dataType指定了为script或jsonp,则无法通过这种方式筛选出来。
  案例分析
  这次搞得还是滑块哦,话不多说直接开搞数美滑块,因为小红书、蘑菇街、脉脉、斗鱼等很多都用了数美的验证码。整体难度还可以就是动态参数有点东西的呢!
  数美验证码官网:
  
  数美滑块的验证码主要的难点有以下几点:
  1.request的请求参数,是动态变化的。名称是动态变化,加密的密钥也是动态变化的,这就有点难搞了
  2.每天小版本更新的频率1-2次,必须得能够实现完全自动化,否则人工很难及时的调整验证码的参数,来不及。
  3.js里的混淆的变量也是动态变化的
  验证码注册
  先看一下register
  
  下图是响应结果:bg和fg是验证码图片地址 bg
  计算滑块位置
  根据上一步可以得到验证图片的地址。
  验证码图片:
  滑块图片:
  使用opencv查找并匹配图像模板中的滑块。
  需要注意的是,这里是以原图计算的,而页面上的图片大小只有(300,150),(应用不同的产品可能大小也不同) 所以需要按比例进行缩小或者放大。
  验证
  对应的api地址是:
  查询字符串参数:
  params参数里的 dv,qe,ou,cf等等,都经过了DES加密。
  破解方式分析
  打开控制台多看几遍请求过程,我们基本就明白请求步骤了。具体的分析过程就不再赘述。
  所携带的请求参数如下:
  
  该接口返回的js参数,是下一步需要请求的目标。
  提取js参数
  js地址:
  需要提取该js中的参数名,会在最后验证的时候使用(注:一般情况下参数名不会变),但是这些请求参数都是变化的。
  获取js的response,搜索上面的参数我们没有找到,但是发现了倒序的名字
  
  通过查看调用栈,打断点,一层层分析,发现js做了ob混淆。
  JS混淆有很多种,这里举几个:UglifyJS,JScrambler,,JSDetox,obfuscator.io 等,像下面的代码就是ob混淆。
  开头定义了一个大数组,然后对这个大数组里的内容进行位移,再定义一个解密函数。后面大部分的值都调用了这个解密函数,以达到混淆的效果。如果想还原可以使用ob混淆还原工具:
  
  当然不进行混淆还原也可以通过断点很快的定位到具体的函数加密的位置
  再次请求走到这里,而这里是一部分的参数的加密,先进去看下它是怎么加密的
  
  进来了走到这可以看到是DES加密,参数分别是加密的密码,要加密的参数,后面两个是数字呢就是模式选择了,1,0是加密,0,0是解密,在这里是加密。
  我们输出在console中输出一下,这四个参数看一下
  
  那么问题来了,这个密码"b64ccadf"哪来的呢,别急,我们重新再来一遍!很快我们又进来走到这,_0x1c2865是什么怎么是乱码的呢?
  
  console输出一下看看
  
  密码搞到了,加密方式也晓得了,然后参数一个一个整过去就Ok了。
  返回结果response:
  message = success,riskLevel=PASS 说明验证通过
  完整代码
<p>"""<br />数美滑块验证码破解验证<br />"""<br /><br />import base64<br />import json<br />import random<br />import re<br />import time<br />from io import BytesIO<br />import cv2<br />import numpy as np<br />import requests<br />from pyDes import des, ECB<br /><br />CAPTCHA_DISPLAY_WIDTH = 310<br />CAPTCHA_DISPLAY_HEIGHT = 155<br /><br />p = {}<br /><br /><br />def pad(b):<br />    """<br />    块填充<br />    """<br />    block_size = 8<br />    while len(b) % block_size:<br />        b += b'\0'<br />    return b<br /><br /><br />def split_args(s):<br />    """<br />    分割js参数<br />    """<br />    r = []<br />    a = ''<br />    i = 0<br />    while i  100:<br />            a = split_args(r)<br />            break<br /><br />    r = re.search(r';\)(.*?)\(}', script[::-1]).group(1)<br />    v = split_args(r[::-1])<br /><br />    d = r'{%s}' % ''.join([((',' if i else '') + '\'k{}\':([_x0-9a-z]*)'.format(i + 1)) for i in range(15)])<br /><br />    k = []<br />    r = re.search(d, script)<br />    for i in range(15):<br />        k.append(r.group(i + 1))<br /><br />    n = int(v[a.index(re.search(r'arguments;.*?,(.*?)\);', script).group(1))], base=16)<br /><br />    for i in range(n // 2):<br />        v[i], v[n - 1 - i] = v[n - 1 - i], v[i]<br /><br />    for i, b in enumerate(k):<br />        t = v[a.index(b)].strip('\'')<br />        names['k{}'.format(i + 1)] = t if len(t) > 2 else t[::-1]<br /><br />    return names<br /><br /><br />def get_encrypt_content(message, key, flag):<br />    """<br />    接口参数的加密、解密<br />    """<br />    des_obj = des(key.encode(), mode=ECB)<br />    if flag:<br />        content = pad(str(message).replace(' ', '').encode())<br />        return base64.b64encode(des_obj.encrypt(content)).decode('utf-8')<br />    else:<br />        return des_obj.decrypt(base64.b64decode(message)).decode('utf-8')<br /><br /><br />def get_random_ge(distance):<br />    """<br />    生成随机的轨迹<br />    """<br />    ge = []<br /><br />    y = 0<br />    v = 0<br />    t = 1<br />    current = 0<br />    mid = distance * 3 / 4<br />    exceed = 20<br />    z = t<br /><br />    ge.append([0, 0, 1])<br /><br />    while current  查看全部

  JS逆向:滑块验证码加密分析
  为什么要做逆向?动态网页爬虫一般可分为两种:Selenium爬取和接口爬取。
  两种方式各有优缺点:
  前者我们己经介绍了selenium的使用和验证码、滑块的使用,其虽然可以很好地处理网页异步加载问题,但面对大型爬虫任务时,效率还是比较低的;
  后者虽然爬取速度较快,但请求参数很可能是动态变化的,这时就需要利用一些前端的知识,重新构造参数,整个过程通常称为JS逆向。
  先来看一下简单的请求:
  
  但是往往在我们编写爬虫时,可能会碰到以下两种问题:造成这种问题原因是,你所正在爬取的页面采取了动态加载的方式动态加载网页其显示的页面则是经过Javascript处理数据后生成的结果,可以发生改变。
  JavaScript是一种运行在浏览器中的解释型编程语言,JavaScript非常值得学习,它既适合作为学习编程的入门语言,也适合当作日常开发的工作语言。
  JavaScript可以收集用户的跟踪数据,不需要重载页面即可直接提交表单,可在页面中嵌入多媒体文件,甚至可以运行网页游戏等。在很多看起来非常简单的页面背后通常使用了许多JavaScript文件。比如:
  
  这些数据的来源有多种,可能是经过Javascript计算生成的,也可能是通过Ajax加载的。Ajax = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),其最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页的内容。
  逆向工程
  对于动态加载的网页,我们想要获取其网页数据,需要了解网页是如何加载数据的,该过程就被成为逆向工程。
  对于使用了Ajax 请求技术的网页,我们可以找到Ajax请求的具体链接,直接得到Ajax请求得到的数据。
  需要注意的是,构造Ajax请求有两种方式:
  原生的Ajax请求,会直接创建一个XMLHTTPRequest对象。
  调用jQuery的ajax()方法。一般情况下,.ajax()会返回其创建的XMLHTTPRequest对象;但是,如果.ajax()的dataType参数指定了为script或jsonp类型,.ajax()不再返回其创建的XMLHTTPRequest对象。
  JQuery补充:
  在大型互联网公司的不断推广下,JavaScript生态圈也在不断的完善,各种类库、API接口层出不穷。
  jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“Write Less,Do More”,即倡导写更少的代码,做更多的事情。
  对于这两种方式,只要创建返回了XMLHTTPRequest对象,就可以通过Chrome浏览器的调试工具在NetWork窗口通过设置XHR过滤条件,直接筛选出Ajax请求的链接;如果是$.ajax()并且dataType指定了为script或jsonp,则无法通过这种方式筛选出来。
  案例分析
  这次搞得还是滑块哦,话不多说直接开搞数美滑块,因为小红书、蘑菇街、脉脉、斗鱼等很多都用了数美的验证码。整体难度还可以就是动态参数有点东西的呢!
  数美验证码官网:
  
  数美滑块的验证码主要的难点有以下几点:
  1.request的请求参数,是动态变化的。名称是动态变化,加密的密钥也是动态变化的,这就有点难搞了
  2.每天小版本更新的频率1-2次,必须得能够实现完全自动化,否则人工很难及时的调整验证码的参数,来不及。
  3.js里的混淆的变量也是动态变化的
  验证码注册
  先看一下register
  
  下图是响应结果:bg和fg是验证码图片地址 bg
  计算滑块位置
  根据上一步可以得到验证图片的地址。
  验证码图片:
  滑块图片:
  使用opencv查找并匹配图像模板中的滑块。
  需要注意的是,这里是以原图计算的,而页面上的图片大小只有(300,150),(应用不同的产品可能大小也不同) 所以需要按比例进行缩小或者放大。
  验证
  对应的api地址是:
  查询字符串参数:
  params参数里的 dv,qe,ou,cf等等,都经过了DES加密。
  破解方式分析
  打开控制台多看几遍请求过程,我们基本就明白请求步骤了。具体的分析过程就不再赘述。
  所携带的请求参数如下:
  
  该接口返回的js参数,是下一步需要请求的目标。
  提取js参数
  js地址:
  需要提取该js中的参数名,会在最后验证的时候使用(注:一般情况下参数名不会变),但是这些请求参数都是变化的。
  获取js的response,搜索上面的参数我们没有找到,但是发现了倒序的名字
  
  通过查看调用栈,打断点,一层层分析,发现js做了ob混淆。
  JS混淆有很多种,这里举几个:UglifyJS,JScrambler,,JSDetox,obfuscator.io 等,像下面的代码就是ob混淆。
  开头定义了一个大数组,然后对这个大数组里的内容进行位移,再定义一个解密函数。后面大部分的值都调用了这个解密函数,以达到混淆的效果。如果想还原可以使用ob混淆还原工具:
  
  当然不进行混淆还原也可以通过断点很快的定位到具体的函数加密的位置
  再次请求走到这里,而这里是一部分的参数的加密,先进去看下它是怎么加密的
  
  进来了走到这可以看到是DES加密,参数分别是加密的密码,要加密的参数,后面两个是数字呢就是模式选择了,1,0是加密,0,0是解密,在这里是加密。
  我们输出在console中输出一下,这四个参数看一下
  
  那么问题来了,这个密码"b64ccadf"哪来的呢,别急,我们重新再来一遍!很快我们又进来走到这,_0x1c2865是什么怎么是乱码的呢?
  
  console输出一下看看
  
  密码搞到了,加密方式也晓得了,然后参数一个一个整过去就Ok了。
  返回结果response:
  message = success,riskLevel=PASS 说明验证通过
  完整代码
<p>"""<br />数美滑块验证码破解验证<br />"""<br /><br />import base64<br />import json<br />import random<br />import re<br />import time<br />from io import BytesIO<br />import cv2<br />import numpy as np<br />import requests<br />from pyDes import des, ECB<br /><br />CAPTCHA_DISPLAY_WIDTH = 310<br />CAPTCHA_DISPLAY_HEIGHT = 155<br /><br />p = {}<br /><br /><br />def pad(b):<br />    """<br />    块填充<br />    """<br />    block_size = 8<br />    while len(b) % block_size:<br />        b += b'\0'<br />    return b<br /><br /><br />def split_args(s):<br />    """<br />    分割js参数<br />    """<br />    r = []<br />    a = ''<br />    i = 0<br />    while i  100:<br />            a = split_args(r)<br />            break<br /><br />    r = re.search(r';\)(.*?)\(}', script[::-1]).group(1)<br />    v = split_args(r[::-1])<br /><br />    d = r'{%s}' % ''.join([((',' if i else '') + '\'k{}\':([_x0-9a-z]*)'.format(i + 1)) for i in range(15)])<br /><br />    k = []<br />    r = re.search(d, script)<br />    for i in range(15):<br />        k.append(r.group(i + 1))<br /><br />    n = int(v[a.index(re.search(r'arguments;.*?,(.*?)\);', script).group(1))], base=16)<br /><br />    for i in range(n // 2):<br />        v[i], v[n - 1 - i] = v[n - 1 - i], v[i]<br /><br />    for i, b in enumerate(k):<br />        t = v[a.index(b)].strip('\'')<br />        names['k{}'.format(i + 1)] = t if len(t) > 2 else t[::-1]<br /><br />    return names<br /><br /><br />def get_encrypt_content(message, key, flag):<br />    """<br />    接口参数的加密、解密<br />    """<br />    des_obj = des(key.encode(), mode=ECB)<br />    if flag:<br />        content = pad(str(message).replace(' ', '').encode())<br />        return base64.b64encode(des_obj.encrypt(content)).decode('utf-8')<br />    else:<br />        return des_obj.decrypt(base64.b64decode(message)).decode('utf-8')<br /><br /><br />def get_random_ge(distance):<br />    """<br />    生成随机的轨迹<br />    """<br />    ge = []<br /><br />    y = 0<br />    v = 0<br />    t = 1<br />    current = 0<br />    mid = distance * 3 / 4<br />    exceed = 20<br />    z = t<br /><br />    ge.append([0, 0, 1])<br /><br />    while current 

Node.js Express 框架

网站优化优采云 发表了文章 • 0 个评论 • 388 次浏览 • 2022-06-23 11:32 • 来自相关话题

  Node.js Express 框架
  接下来我们扩展 Hello World,添加一些功能来处理更多类型的 HTTP 请求。
  创建 express_demo2.js 文件,代码如下所示:
  express_demo2.js 文件代码:
  var express = require('express');var app = express(); // 主页输出 "Hello World"app.get('/', function (req, res) { console.log("主页 GET 请求"); res.send('Hello GET');}) // POST 请求app.post('/', function (req, res) { console.log("主页 POST 请求"); res.send('Hello POST');}) // /del_user 页面响应app.get('/del_user', function (req, res) { console.log("/del_user 响应 DELETE 请求"); res.send('删除页面');}) // /list_user 页面 GET 请求app.get('/list_user', function (req, res) { console.log("/list_user GET 请求"); res.send('用户列表页面');}) // 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求app.get('/ab*cd', function(req, res) { console.log("/ab*cd GET 请求"); res.send('正则匹配');}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node express_demo2.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  接下来你可以尝试访问 :8081 不同的地址,查看效果。
  在浏览器中访问 :8081/list_user,结果如下图所示:
  
  在浏览器中访问 :8081/abcd,结果如下图所示:
  
  在浏览器中访问 :8081/abcdefg,结果如下图所示:
  
  静态文件
  Express 提供了内置的中间件express.static来设置静态文件如:图片, CSS, JavaScript 等。
  你可以使用express.static中间件来设置静态文件路径。例如,如果你将图片, CSS, JavaScript 文件放在 public 目录下,你可以这么写:
  app.use('/public', express.static('public'));
  我们可以到 public/images 目录下放些图片,如下所示:
  node_modules<br />server.js<br />public/public/images<br />public/images/logo.png
  让我们再修改下 "Hello World" 应用添加处理静态文件的功能。
  创建 express_demo3.js 文件,代码如下所示:
  express_demo3.js 文件代码:
  var express = require('express');var app = express(); app.use('/public', express.static('public')); app.get('/', function (req, res) { res.send('Hello World');}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node express_demo3.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  执行以上代码:
  在浏览器中访问 :8081/public/images/logo.png(本实例采用了菜鸟教程的 logo),结果如下图所示:
  
  GET 方法
  以下实例演示了在表单中通过 GET 方法提交两个参数,我们可以使用 server.js 文件内的process_get路由器来处理输入:
  index.html 文件代码:
  First Name: Last Name:
  server.js 文件代码:
  var express = require('express');var app = express(); app.use('/public', express.static('public')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.get('/process_get', function (req, res) { // 输出 JSON 格式 var response = { "first_name":req.query.first_name, "last_name":req.query.last_name }; console.log(response); res.end(JSON.stringify(response));}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  node server.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  POST 方法
  以下实例演示了在表单中通过 POST 方法提交两个参数,我们可以使用 server.js 文件内的process_post路由器来处理输入:
  index.html 文件代码:
  First Name: Last Name:
  server.js 文件代码:
  var express = require('express');var app = express();var bodyParser = require('body-parser'); // 创建 application/x-www-form-urlencoded 编码解析var urlencodedParser = bodyParser.urlencoded({ extended: false }) app.use('/public', express.static('public')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.post('/process_post', urlencodedParser, function (req, res) { // 输出 JSON 格式 var response = { "first_name":req.body.first_name, "last_name":req.body.last_name }; console.log(response); res.end(JSON.stringify(response));}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node server.js<br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  文件上传
  以下我们创建一个用于上传文件的表单,使用 POST 方法,表单 enctype 属性设置为 multipart/form-data。
  index.html 文件代码:
  文件上传表单文件上传:选择一个文件上传:
  server.js 文件代码:
  var express = require('express');var app = express();var fs = require("fs"); var bodyParser = require('body-parser');var multer = require('multer'); app.use('/public', express.static('public'));app.use(bodyParser.urlencoded({ extended: false }));app.use(multer({ dest: '/tmp/'}).array('image')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.post('/file_upload', function (req, res) { console.log(req.files[0]); // 上传的文件信息 var des_file = __dirname + "/" + req.files[0].originalname; fs.readFile( req.files[0].path, function (err, data) { fs.writeFile(des_file, data, function (err) { if( err ){ console.log( err ); }else{ response = { message:'File uploaded successfully', filename:req.files[0].originalname }; } console.log( response ); res.end( JSON.stringify( response ) ); }); });}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node server.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  Cookie 管理
  我们可以使用中间件向 Node.js 服务器发送 cookie 信息,以下代码输出了客户端发送的 cookie 信息:
  express_cookie.js 文件代码:
  // express_cookie.js 文件var express = require('express')var cookieParser = require('cookie-parser')var util = require('util'); var app = express()app.use(cookieParser()) app.get('/', function(req, res) { console.log("Cookies: " + util.inspect(req.cookies));}) app.listen(8081)
  执行以上代码:
  $ node express_cookie.js
  现在你可以访问 :8081 并查看终端信息的输出,如下演示:
  
  相关资料 查看全部

  Node.js Express 框架
  接下来我们扩展 Hello World,添加一些功能来处理更多类型的 HTTP 请求。
  创建 express_demo2.js 文件,代码如下所示:
  express_demo2.js 文件代码:
  var express = require('express');var app = express(); // 主页输出 "Hello World"app.get('/', function (req, res) { console.log("主页 GET 请求"); res.send('Hello GET');}) // POST 请求app.post('/', function (req, res) { console.log("主页 POST 请求"); res.send('Hello POST');}) // /del_user 页面响应app.get('/del_user', function (req, res) { console.log("/del_user 响应 DELETE 请求"); res.send('删除页面');}) // /list_user 页面 GET 请求app.get('/list_user', function (req, res) { console.log("/list_user GET 请求"); res.send('用户列表页面');}) // 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求app.get('/ab*cd', function(req, res) { console.log("/ab*cd GET 请求"); res.send('正则匹配');}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node express_demo2.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  接下来你可以尝试访问 :8081 不同的地址,查看效果。
  在浏览器中访问 :8081/list_user,结果如下图所示:
  
  在浏览器中访问 :8081/abcd,结果如下图所示:
  
  在浏览器中访问 :8081/abcdefg,结果如下图所示:
  
  静态文件
  Express 提供了内置的中间件express.static来设置静态文件如:图片, CSS, JavaScript 等。
  你可以使用express.static中间件来设置静态文件路径。例如,如果你将图片, CSS, JavaScript 文件放在 public 目录下,你可以这么写:
  app.use('/public', express.static('public'));
  我们可以到 public/images 目录下放些图片,如下所示:
  node_modules<br />server.js<br />public/public/images<br />public/images/logo.png
  让我们再修改下 "Hello World" 应用添加处理静态文件的功能。
  创建 express_demo3.js 文件,代码如下所示:
  express_demo3.js 文件代码:
  var express = require('express');var app = express(); app.use('/public', express.static('public')); app.get('/', function (req, res) { res.send('Hello World');}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node express_demo3.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  执行以上代码:
  在浏览器中访问 :8081/public/images/logo.png(本实例采用了菜鸟教程的 logo),结果如下图所示:
  
  GET 方法
  以下实例演示了在表单中通过 GET 方法提交两个参数,我们可以使用 server.js 文件内的process_get路由器来处理输入:
  index.html 文件代码:
  First Name: Last Name:
  server.js 文件代码:
  var express = require('express');var app = express(); app.use('/public', express.static('public')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.get('/process_get', function (req, res) { // 输出 JSON 格式 var response = { "first_name":req.query.first_name, "last_name":req.query.last_name }; console.log(response); res.end(JSON.stringify(response));}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  node server.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  POST 方法
  以下实例演示了在表单中通过 POST 方法提交两个参数,我们可以使用 server.js 文件内的process_post路由器来处理输入:
  index.html 文件代码:
  First Name: Last Name:
  server.js 文件代码:
  var express = require('express');var app = express();var bodyParser = require('body-parser'); // 创建 application/x-www-form-urlencoded 编码解析var urlencodedParser = bodyParser.urlencoded({ extended: false }) app.use('/public', express.static('public')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.post('/process_post', urlencodedParser, function (req, res) { // 输出 JSON 格式 var response = { "first_name":req.body.first_name, "last_name":req.body.last_name }; console.log(response); res.end(JSON.stringify(response));}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node server.js<br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  文件上传
  以下我们创建一个用于上传文件的表单,使用 POST 方法,表单 enctype 属性设置为 multipart/form-data。
  index.html 文件代码:
  文件上传表单文件上传:选择一个文件上传:
  server.js 文件代码:
  var express = require('express');var app = express();var fs = require("fs"); var bodyParser = require('body-parser');var multer = require('multer'); app.use('/public', express.static('public'));app.use(bodyParser.urlencoded({ extended: false }));app.use(multer({ dest: '/tmp/'}).array('image')); app.get('/index.html', function (req, res) { res.sendFile( __dirname + "/" + "index.html" );}) app.post('/file_upload', function (req, res) { console.log(req.files[0]); // 上传的文件信息 var des_file = __dirname + "/" + req.files[0].originalname; fs.readFile( req.files[0].path, function (err, data) { fs.writeFile(des_file, data, function (err) { if( err ){ console.log( err ); }else{ response = { message:'File uploaded successfully', filename:req.files[0].originalname }; } console.log( response ); res.end( JSON.stringify( response ) ); }); });}) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("应用实例,访问地址为 http://%s:%s", host, port) })
  执行以上代码:
  $ node server.js <br />应用实例,访问地址为 http://0.0.0.0:8081
  浏览器访问 :8081/index.html,如图所示:
  
  现在你可以向表单输入数据,并提交,如下演示:
  
  Cookie 管理
  我们可以使用中间件向 Node.js 服务器发送 cookie 信息,以下代码输出了客户端发送的 cookie 信息:
  express_cookie.js 文件代码:
  // express_cookie.js 文件var express = require('express')var cookieParser = require('cookie-parser')var util = require('util'); var app = express()app.use(cookieParser()) app.get('/', function(req, res) { console.log("Cookies: " + util.inspect(req.cookies));}) app.listen(8081)
  执行以上代码:
  $ node express_cookie.js
  现在你可以访问 :8081 并查看终端信息的输出,如下演示:
  
  相关资料

官方客服QQ群

微信人工客服

QQ人工客服


线