Python反爬JS逆向解析(七)-----某不知名网站js加密cookie反爬_execjs._exceptions.programerror: referenceerror: d-程序员宅基地

技术标签: 爬虫Web  

采集前建议:找好代理IP,别对该网站发起攻击性访问,否则爬虫用的好,监狱进的早

1.网站:

点此直达该不知名网站

                                                                         

2.正常请求网站:

拿到网址,查看完基本的信息后,应该就是用代码对网站发起请求了。

# -*- coding: UTF-8 -*-
'''
@Author :Jason
没有代理的自己找个代理,没的话也可去掉代理
'''
import requests,random
from pprint import pprint
proxies = random.choice([
    {"HTTPS":""}
    ])

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}

res = requests.get(url= "https://www.mps.gov.cn/n2253534/n2253535/index.html",proxies=proxies,headers = headers)
pprint(res.text)

打印内容:

<script>var x="1500@join@match@0xEDB88320@@@Expires@@attachEvent@Mar@@document@@cSELK@charAt@Array@reverse@firstChild@4@onreadystatechange@@nQ@for@0xFF@@addEventListener@@createElement@a@false@replace@@@24@08@@@6@@0@20@1584861863@@@challenge@b@p@search@8@@setTimeout@@cookie@3@catch@f@div@@@36@d@return@toLowerCase@@@2@href@var@fromCharCode@e@@Sun@22@33@@@String@try@window@pathname@@captcha@JgSe0upZ@Path@@@charCodeAt@new@DOMContentLoaded@parseInt@@@RegExp@@@GMT@https@@@eval@split@innerHTML@@if@function@BDjajy@g@@substr@while@23@length@toString@@@rOm9XFMtA3QKV7nYsPGT4lifyWwkq5vcjH2IdxUoCbhERLaz81DNB6@@@@@0v@@__jsl_clearance@1@else@chars@@location".replace(/@*$/,"").split("@"),y="2e 1g=3o(){1o('4k.2d=4k.2q+4k.1l.14(/[\\?|&]31-1i/,\\'\\')',1);c.1q='4f=1f.2k|1d|'+(3o(){2e 46=[3o(1g){28 1g},3o(46){28 46},(3o(){2e 1g=c.11('23');1g.3l='<12 2d=\\'/\\'>3m</12>';1g=1g.i.2d;2e 46=1g.3(/3g?:\\/\\//)[1d];1g=1g.41(46.44).29();28 3o(46){n(2e 3m=1d;3m<46.44;3m++){46[3m]=1g.f(46[3m])};28 46.2('')}})(),3o(1g){28 3j('2n.2f('+1g+')')}],3m=['1k',[(((+!-{})|(-~[]<<-~[]))+[]+[])+[(-~[]+[j]>>-~[])]],(2c+[]+[]),[[(-~[]+[j]>>-~[])]+((+![])+[]+[[]][1d])],'m',[[(+!-{})]+(2c+[]+[])],'e',[![]+[]+[[]][1d]][1d].f((-~[]<<-~[])),'1j',(2c+[]+[]),'3p',[(-~((-~[]+[-~(+!-{})]>>-~(+!-{})))+(-~[]<<-~[])+((-~[]<<-~[])^(+!-{}))+[[]][1d])],'4d',[[(+!-{})]+(2c+[]+[])+((+![])+[]+[[]][1d])],(-~((-~[]+[-~(+!-{})]>>-~(+!-{})))+[]),[(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+j+[])+[2c+(2c^(+!-{}))]],[(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+j+[])],[(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+j+[])+[2c+(2c^(+!-{}))],(((+!-{})|(-~[]<<-~[]))+[]+[])+[(-~[]+[j]>>-~[])]],(((+!-{})|(-~[]<<-~[]))+[]+[]),[[1b]+(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+j+[])]];n(2e 1g=1d;1g<3m.44;1g++){3m[1g]=46[[4g,20,1d,20,4g,2c,4g,1d,4g,1d,4g,2c,4g,20,1d,20,2c,20,1d,20][1g]](3m[1g])};28 3m.2('')})()+';7=2i, 2j-a-1e 18:17:43 3f;33=/;'};3n((3o(){2o{28 !!2p.q;}21(2g){28 13;}})()){c.q('38',1g,13)}4h{c.9('k',1g)}",f=function(x,y){var a=0,b=0,c=0;x=x.split("");y=y||99;while((a=x.shift())&&(b=a.charCodeAt(0)-77.5))c=(Math.abs(b)<13?(b+48.5):parseInt(a,36))+y*c;return c},z=f(y.match(/\w/g).sort(function(x,y){return f(x)-f(y)}).pop());while(z++)try{eval(y.replace(/\b\w+\b/g, function(y){return x[f(y,z)-1]||("_"+y)}));break}catch(_){}</script>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             

这样看费眼费脑,我们需要将JS代码格式化(美化):

<script>
	var x = "@join@window@g@@e@chars@Mar@charCodeAt@eval@@toString@@@@search@String@@fromCharCode@@var@8@onreadystatechange@@function@@reverse@4@new@replace@Thu@@@@substr@19@GMT@attachEvent@@false@length@__jsl_clearance@@@08@@0xEDB88320@@0xFF@match@@parseInt@cookie@DOMContentLoaded@for@firstChild@1@0@setTimeout@6@captcha@RegExp@f@@@div@document@@charAt@location@pathname@@return@https@d@@@else@href@Expires@@try@rOm9XFMtA3QKV7nYsPGT4lifyWwkq5vcjH2IdxUoCbhERLaz81DNB6@@while@2@innerHTML@@@@@catch@@36@099@Path@@@@@20@toLowerCase@@55@@@@@createElement@split@challenge@@@if@52@addEventListener@@Array@@a@JgSe0upZ@@@1584604552@1500@@@".replace(/@*$/, "").split("@"),
	y = "l M=p(){15('1g.1p=1g.1h+1g.g.u(/[\\?|&]17-23/,\\'\\')',2h);1d.R='G=2g.1F|14|'+(p(){l 1K=[p(M){1j a('h.j('+M+')')},p(M){11(l 1K=14;1K<M.F;1K++){M[1K]=Q(M[1K]).c(1E)};1j M.2('')}],M=[[[(+!-{})]+[16],(1w+[]+[])+[16],(1w+[]+[])+[1w+(1w^(+!-{}))],[(+!-{})]+(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+s+[]),[(+!-{})]+((+![])+[]+[[]][14]),[(+!-{})]+(((+!-{})|(-~[]<<-~[]))+[]+[])],[(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+s+[])+(-~((-~[]+[-~(+!-{})]>>-~(+!-{})))+(-~[]<<-~[])+((-~[]<<-~[])^(+!-{}))+[[]][14]),[1w+(1w^(+!-{}))]+(-~((-~[]+[-~(+!-{})]>>-~(+!-{})))+[])],[(1w+[]+[])+[(+!-{})],[(+!-{})]+(-~((-~[]+[-~(+!-{})]>>-~(+!-{})))+[]),[(+!-{})]+[16]],[[1w+(1w^(+!-{}))]+(((+!-{})|(-~[]<<-~[]))+[]+[]),[16]+[1w+(1w^(+!-{}))],(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+s+[])+[(-~[]+[s]>>-~[])]],[(((+!-{})|(-~[]<<-~[]))+[]+[])+((+![])+[]+[[]][14])],[[(-~[]+[s]>>-~[])]+[1w+(1w^(+!-{}))],(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+s+[])+(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+s+[])],[[(+!-{})]+[16]],[[(-~[]+[s]>>-~[])]+((+![])+[]+[[]][14]),[(-~[]+[s]>>-~[])]+[(+!-{})],[1w+(1w^(+!-{}))]+(((+!-{})|(-~[]<<-~[]))+[]+[]),[1w+(1w^(+!-{}))]+[1w+(1w^(+!-{}))],[(-~[]+[s]>>-~[])]+(((+!-{})|(-~[]<<-~[]))+[]+[]),[(-~[]+[s]>>-~[])]+(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+s+[])],[[(+!-{})]+(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+s+[]),(1w+[]+[])+[16]],[[16]+[1w+(1w^(+!-{}))],(((+!-{})|(-~[]<<-~[]))+[]+[])+[(-~[]+[s]>>-~[])],[1w+(1w^(+!-{}))]+[(+!-{})],[16]+(-~[]+(-~[]+[-~(+!-{})]>>-~(+!-{}))+s+[])]];11(l 1I=14;1I<M.F;1I++){M[1I]=1K.r()[((+![])+[]+[[]][14])](M[1I])};1j M.2('')})()+';1q=v, A-8-1L J:1O:27 B;1G=/;'};26((p(){1s{1j !!3.28;}1C(6){1j E;}})()){1d.28('10',M,E)}1o{1d.C('n',M)}",
	f = function(x, y) {
		var a = 0,
		b = 0,
		c = 0;
		x = x.split("");
		y = y || 99;
		while ((a = x.shift()) && (b = a.charCodeAt(0) - 77.5)) c = (Math.abs(b) < 13 ? (b + 48.5) : parseInt(a, 36)) + y * c;
		return c
	},
	z = f(y.match(/\w/g).sort(function(x, y) {
		return f(x) - f(y)
	}).pop());
	while (z++) try {
		eval(y.replace(/\b\w+\b/g,
		function(y) {
			return x[f(y, z) - 1] || ("_" + y)
		}));
		break
	} catch(_) {}
</script>

<script></script>标签,很明显返回的内容只是一段JS代码,并不是我们需要的数据,先大略搂一眼这茬JS就行了。

3.分析:

再次对网站发起请求,Fiddler抓包

其中#1就是我们获取到的JS代码(如下图),但是状态码有点奇怪哈,521,我们都知道状态码5XX表示的是内部服务器(HTTP-Internal Server Error)错误说明IIS服务器无法解析ASP代码,也就是说这是服务器本身的错误,而不是我们的请求错误,继续。。。

#2,#4的话没看出啥作用来(其实是我这个渣渣没看出啥作用来,懂得可以评论帮我解释下)

#3的话就是我们需要的数据了

       图略,自行查看,太优秀导致无法过审。

到此,#1,#2,#3,#4基本就是从发起请求到请求结束(获取到我们需要的数据)

                                    

看完后好像并没有什么发现?

对比一下#1和#3两个请求,我们发现请求只是请求时请求头稍微不同,设置并增加了一个cookie

          

                      

随便点击新闻页面的一个新闻,观察Fiddler的抓包情况,发现已经可以正常获得页面了,而新闻页面和#3的cookie是一样的。很明显了,网站进行了cookie验证,脚本带上cookie发起请求,是可以直接将数据请求过来的。

如果你只是需要采集一遍数据的话,那么直接将JS、复制过来也是可以用的,但是,作为长久之计,我们还是需要搞懂cookie的来龙去脉。

4.解析

先分析cookie值

设置:Set-Cookie: __jsluid_s=669f5e06a3b3f2fd2679ef2f4ca91ce6; max-age=31536000; path=/; HttpOnly; secure


最后需要的:Cookie: __jsluid_s=669f5e06a3b3f2fd2679ef2f4ca91ce6; __jsl_clearance=1584607180.68|0|b9aYrP21LoBfBNdYNlcLmJlEhbI%3D

 #1状态码521时设置了cookie(Set-Cookie),再次发起请求时Cookie又有点不一样了,多了一个__jsl_clearance。其中__jsluid_s在发起请求时我们可以轻松拿到,__jsl_clearance=1584607180.68|0|b9aYrP21LoBfBNdYNlcLmJlEhbI%3D,其中第一截凭感觉像是时间戳(虽然它就是,但是我们还是需要验证的,毕竟时间戳上还是有很多手脚可以做的),第二截0,第三截看不出来,但是从%3D我们大致可以知道,这难道是经过URL编码?没法,我们到回之前对之前获取到的JS代码进行处理吧!!!

JS代码美化,eval=>console.log(),在控制台输入加打印

JS代码美化,细分析,查看参数和函数等,其中看到了我们需要的__jsl_clearance参数

var _M = function() {
	setTimeout('location.href=location.pathname+location.search.replace(/[\?|&]captcha-challenge/,\'\')', 1500);
	document.cookie = '__jsl_clearance=1584606567.057|0|' + (function() {
		var _1K = [function(_M) {
			return eval('String.fromCharCode(' + _M + ')')
		},
		function(_M) {
			for (var _1K = 0; _1K < _M.length; _1K++) {
				_M[_1K] = parseInt(_M[_1K]).toString(36)
			};
			return _M.join('')
		}],
		_M = [[[2 + (2 ^ ( + !-{}))] + [( + !-{})]], [[( + !-{})] + ( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + []), [( + !-{})] + ((( + !-{}) | ( - ~ [] << -~ [])) + [] + [])], [( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + []) + (2 + [] + [])], [(2 + [] + []) + [2 + (2 ^ ( + !-{}))]], [( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + []) + [2 + (2 ^ ( + !-{}))]], [[( + !-{})] + [( - ~ [] + [4] >> -~ [])]], [[2 + (2 ^ ( + !-{}))] + (2 + [] + [])], [[( + !-{})] + [( + !-{})]], [[( - ~ [] + [4] >> -~ [])] + ( - ~ (( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{}))) + [])], [((( + !-{}) | ( - ~ [] << -~ [])) + [] + []) + ((( + !-{}) | ( - ~ [] << -~ [])) + [] + [])], [((( + !-{}) | ( - ~ [] << -~ [])) + [] + []) + [( - ~ [] + [4] >> -~ [])], [2 + (2 ^ ( + !-{}))] + (( + ![]) + [] + [[]][0]), [6] + [6]], [[( + !-{})] + ( - ~ (( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{}))) + ( - ~ [] << -~ []) + (( - ~ [] << -~ []) ^ ( + !-{})) + [[]][0])], [[( - ~ [] + [4] >> -~ [])] + [2 + (2 ^ ( + !-{}))], [( - ~ [] + [4] >> -~ [])] + (2 + [] + [])], [(2 + [] + []) + [( - ~ [] + [4] >> -~ [])]], [[2 + (2 ^ ( + !-{}))] + [( - ~ [] + [4] >> -~ [])]], [((( + !-{}) | ( - ~ [] << -~ [])) + [] + []) + [( + !-{})]], [( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + []) + (2 + [] + []), ( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + []) + ( - ~ (( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{}))) + ( - ~ [] << -~ []) + (( - ~ [] << -~ []) ^ ( + !-{})) + [[]][0]), [( - ~ [] + [4] >> -~ [])] + [6], ( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + []) + ( - ~ (( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{}))) + [])], [((( + !-{}) | ( - ~ [] << -~ [])) + [] + []) + ((( + !-{}) | ( - ~ [] << -~ [])) + [] + []), [( + !-{})] + ( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + [])], [[( - ~ [] + [4] >> -~ [])] + ( - ~ (( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{}))) + ( - ~ [] << -~ []) + (( - ~ [] << -~ []) ^ ( + !-{})) + [[]][0]), ( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + []) + (2 + [] + []), [( - ~ [] + [4] >> -~ [])] + ((( + !-{}) | ( - ~ [] << -~ [])) + [] + []), ((( + !-{}) | ( - ~ [] << -~ [])) + [] + []) + [( - ~ [] + [4] >> -~ [])], [2 + (2 ^ ( + !-{}))] + [( + !-{})], [6] + ( - ~ [] + ( - ~ [] + [ - ~ ( + !-{})] >> -~ ( + !-{})) + 4 + [])]];
		for (var _1I = 0; _1I < _M.length; _1I++) {
			_M[_1I] = _1K.reverse()[[( + !-{})]](_M[_1I])
		};
		return _M.join('')
	})() + ';Expires=Thu, 19-Mar-20 09:29:27 GMT;Path=/;'
};
if ((function() {
	try {
		return !! window.addEventListener;
	} catch(e) {
		return false;
	}
})()) {
	document.addEventListener('DOMContentLoaded', _M, false)
} else {
	document.attachEvent('onreadystatechange', _M)
}

 再次控制台打印,结果:

 

是的,我们需要的cookie值已经拿到了,最后,我们只需要通过代码实现就可以了。

5.填坑:

步步为营,其中遇到很多坑,一个一个详细介绍解决方法:

坑一:

execjs._exceptions.ProgramError: ReferenceError: document is not defined

具体解决方法参考博客:Python 解决execjs._exceptions.ProgramError: ReferenceError: document is not defined报错问题

坑二:

execjs._exceptions.ProgramError: ReferenceError: window is not defined

错误类型:window对象未定义

解决方法一: 定义对象:

var window = {};

解决方法二:替换

  replace("window", "'Chrome'")

以上两个方法都行,继续

坑三:前后两次访问的User-Agent一定要相同,不然还是不行(深有体会系列)

 

6.Python代码实现: 

填完坑,清完雷,继续玩下走,就是代码了,部分代码如下:

 获取cookie

 携带cookie访问:

最后main函数调起程序:

                                            

 声明:文章仅源自个人兴趣爱好,不涉及他用,侵权联系删。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36853469/article/details/105022598

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签