【转】深入浅出PageRank算法

原文链接 http://segmentfault.com/a/1190000000711128

PageRank算法

PageRank算法是谷歌曾经独步天下的“倚天剑”,该算法由Larry Page和Sergey Brin在斯坦福大学读研时发明的,

论文点击下载: The PageRank Citation Ranking: Bringing Order to the Web。

本文首先通过一些参考文献引出问题,然后给出了PageRank的几种实现算法,

最后将其推广至在MapReduce框架下如何实现PageRank算法。

PageRank的核心思想有2点:

1.如果一个网页被很多其他网页链接到的话说明这个网页比较重要,也就是pagerank值会相对较高;

2.如果一个pagerank值很高的网页链接到一个其他的网页,那么被链接到的网页的pagerank值会相应地因此而提高。

下面是一张来自WikiPedia的图,每个球代表一个网页,球的大小反应了网页的pagerank值的大小。

指向网页B和网页E的链接很多,所以B和E的pagerank值较高,另外,虽然很少有网页指向C,

但是最重要的网页B指向了C,所以C的pagerank值比E还要大。

image

参考内容:

1.Wiki about PageRank

2.Google 的秘密- PageRank 彻底解说 中文版

3.数值分析与算法 Page 161 应用实例:Google的PageRank算法

4.Numeric Methods with Matlab 或者中文翻译版本Matlab数值计算

5.使用 MapReduce 思想计算 PageRank Page 62 PageRank和马尔可夫链

1.问题背景

来自参考内容3

image

2.数学建模

来自参考内容3,理解网页连接矩阵$G$,马尔科夫过程("网上冲浪"),转移矩阵$A$,概率$p$为用户点击当前网页中的某个链接地址的概率(一般都为0.85)。

image
image

最后得到一个等式$Ax=x$,这实际上就是求矩阵$A$的特征值为1的特征向量!

下面的内容使用圆盘定理解释了1是矩阵$A$的主特征值,所以我们可以使用幂法来求解。

关于幂法的详细介绍参考另一篇文章Numerical Methods Using Matlab: 第三章 矩阵特征值和奇异值求解

image
image

3.求解PageRank

假设有如上图右侧所示的网页链接模型。

(1) 幂法

wiki上有一个PageRank的简便算法,它不考虑转移概率,而是采用的是迭代的方式,每次都更新所有网页的pagerank值,更新的方式就是将每个网页的pagerank值平摊分给它指向的所有网页,每个网页累计所有指向它的网页平摊给它的值作为它该回合的pagerank值,直到全部网页的pagerank值收敛了或者满足一定的阈值条件就停止。

后面的MapReduce框架下PageRank算法的实现就采用了这个思想。考虑转移概率的情况和这个算法类似,乘上一个转移概率再加上一个随机跳转的概率。

image

根据上面的思想,下面Matlab代码实现可以得到各个网页的PageRank值。

n=6;
i=[2 3 4 4 5 6 1 6 1]; j=[1 2 2 3 3 3 4 5 6]; G=sparse(i,j,1,n,n); % Power method for j = 1:n L{j} = find(G(:,j)); c(j) = length(L{j}); end p = .85; delta = (1-p)/n; x = ones(n,1)/n; z = zeros(n,1); cnt = 0; while max(abs(x-z)) > .0001 z = x; x = zeros(n,1); for j = 1:n if c(j) == 0 x = x + z(j)/n;%转移到任意一个网页 else x(L{j}) = x(L{j}) + z(j)/c(j);%将上次的pagerank值平摊给所有指向的网页 end end x = p*x + delta; cnt = cnt+1; end 

得到的向量$x$保存了各个网页的pagerank值,虽然链接数目一样,但是网页①比网页④和网页⑤都高,而网页②的pagerank值第二高,因为网页①链接到了它上面,相当于沾了网页①的光。

x =0.26750.2524 0.1323 0.1698 0.0625 0.1156 

这篇文章给出该算法的一个Python版本实现,该博主使用第三方模块python-graph,python-graph模块实现了很多图算法,该模块的使用示例,使用前需要先安装,代码如下:

easy_install python-graph-core
easy_install python-graph-dot

Python版本的算法实现:

# coding=utf-8# python-graph https://code.google.com/p/python-graph/# Import graphviz
import graphviz as gv # Import pygraph from pygraph.classes.digraph import digraph from pygraph.readwrite.dot import write # Define pagerank function def pagerank(graph, damping_factor=0.85, max_iterations=100, \ min_delta=0.00001): """ Compute and return the PageRank in an directed graph. @type graph: digraph @param graph: Digraph. @type damping_factor: number @param damping_factor: PageRank dumping factor. @type max_iterations: number @param max_iterations: Maximum number of iterations. @type min_delta: number @param min_delta: Smallest variation required for a new iteration. @rtype: Dict @return: Dict containing all the nodes PageRank. """ nodes = graph.nodes() graph_size = len(nodes) if graph_size == 0: return {} # value for nodes without inbound links min_value = (1.0-damping_factor)/graph_size # itialize the page rank dict with 1/N for all nodes #pagerank = dict.fromkeys(nodes, 1.0/graph_size) pagerank = dict.fromkeys(nodes, 1.0) for i in range(max_iterations): diff = 0 #total difference compared to last iteraction # computes each node PageRank based on inbound links for node in nodes: rank = min_value for referring_page in graph.incidents(node): rank += damping_factor * pagerank[referring_page] / \ len(graph.neighbors(referring_page)) diff += abs(pagerank[node] - rank) pagerank[node] = rank print 'This is NO.%s iteration' % (i+1) print pagerank print '' #stop if PageRank has converged if diff < min_delta: break return pagerank # Graph creation gr = digraph() # Add nodes and edges gr.add_nodes(["1","2","3","4"]) gr.add_edge(("1","2")) gr.add_edge(("1","3")) gr.add_edge(("1","4")) gr.add_edge(("2","3")) gr.add_edge(("2","4")) gr.add_edge(("3","4")) gr.add_edge(("4","2")) # Draw as PNG # dot = write(gr) # gvv = gv.readstring(dot) # gv.layout(gvv,'dot') # gv.render(gvv,'png','Model.png') pagerank(gr) 

经过32次迭代之后得到的结果如下,和前面的结果一致:

This is NO.32 iteration
{'1': 0.2675338708706491, '3': 0.13227261904986046, '2': 0.2524037902400518, '5': 0.062477242064127136, '4': 0.1697488529161491, '6': 0.1155828978186352} 

(2) 利用马尔可夫矩阵的特殊结构

来自参考内容4,其中$\delta=\frac{1-p}{n}$

image

也就是将矩阵$A$进行分解,并不需要显示求出矩阵$A$,然后便是求解一个线性方程组即可。

function x = pagerank1(G)
% PAGERANK1  Google's PageRank modified version 1 - hujiawei%if nargin < 3, p = .85; end
p=0.85;% Eliminate any self-referential linksG = G - diag(diag(G));% c = out-degree, r = in-degree[n,n] = size(G);
c = sum(G,1);%each row's sum
r = sum(G,2);%each col's sum% Scale column sums to be 1 (or 0 where there are no out links).k = find(c~=0); D = sparse(k,k,1./c(k),n,n); % Solve (I - p*G*D)*x = e e = ones(n,1); I = speye(n,n); x = (I - p*G*D)\e; % Normalize so that sum(x) == 1. x = x/sum(x); 

(3) 巧妙解法:逆迭代算法

巧妙利用Matlab中的精度误差导致原本是一个奇异矩阵的$I-A$变成一个非奇异矩阵,运行时只是会有些警告提示,但是运行结果和其他算法一样。

image

function x = pagerank2(G)
% PAGERANK1  Google's PageRank modified version 2 - hujiawei
% using inverse iteration method%if nargin < 3, p = .85; end
p=0.85;% Eliminate any self-referential linksG = G - diag(diag(G));% c = out-degree, r = in-degree[n,n] = size(G);
c = sum(G,1);%each row's sum
r = sum(G,2);%each col's sum% Scale column sums to be 1 (or 0 where there are no out links).k = find(c~=0); D = sparse(k,k,1./c(k),n,n); % Solve (I - p*G*D)*x = e e = ones(n,1); I = speye(n,n); % x = (I - p*G*D)\e; delta=(1-p)/n; A=p*G*D+delta; x=(I-A)\e; % Normalize so that sum(x) == 1. x = x/sum(x); 

最后,附上参考内容4中给出的一份好代码,用于模拟随机冲浪生成矩阵$G$的代码

function [U,G] = surfer(root,n)
% SURFER  Create the adjacency graph of a portion of the Web.
%    [U,G] = surfer(root,n) starts at the URL root and follows
%    Web links until it forms an adjacency graph with n nodes.
%    U = a cell array of n strings, the URLs of the nodes.
%    G = an n-by-n sparse matrix with G(i,j)=1 if node j is linked to node i.
%
%    Example:  [U,G] = surfer('http://www.harvard.edu',500); % See also PAGERANK. % % This function currently has two defects. (1) The algorithm for % finding links is naive. We just look for the string 'http:'. % (2) An attempt to read from a URL that is accessible, but very slow, % might take an unacceptably long time to complete. In some cases, % it may be necessary to have the operating system terminate MATLAB. % Key words from such URLs can be added to the skip list in surfer.m. % Initialize clf shg set(gcf,'doublebuffer','on') axis([0 n 0 n]) axis square axis ij box on set(gca,'position',[.12 .20 .78 .78]) uicontrol('style','frame','units','normal','position',[.01 .09 .98 .07]); uicontrol('style','frame','units','normal','position',[.01 .01 .98 .07]); t1 = uicontrol('style','text','units','normal','position',[.02 .10 .94 .04], ... 'horiz','left'); t2 = uicontrol('style','text','units','normal','position',[.02 .02 .94 .04], ... 'horiz','left'); slow = uicontrol('style','toggle','units','normal', ... 'position',[.01 .24 .07 .05],'string','slow','value',0); quit = uicontrol('style','toggle','units','normal', ... 'position',[.01 .17 .07 .05],'string','quit','value',0); U = cell(n,1); hash = zeros(n,1); G = logical(sparse(n,n)); m = 1; U{m} = root; hash(m) = hashfun(root); j = 1; while j < n & get(quit,'value') == 0 % Try to open a page. try set(t1,'string',sprintf('%5d %s',j,U{j})) set(t2,'string',''); drawnow page = urlread(U{j}); catch set(t1,'string',sprintf('fail: %5d %s',j,U{j})) drawnow continue end if get(slow,'value') pause(.25) end % Follow the links from the open page. for f = findstr('http:',page); % A link starts with 'http:' and ends with the next quote. e = min([findstr('"',page(f:end)) findstr('''',page(f:end))]); if isempty(e), continue, end url = deblank(page(f:f+e-2)); url(url<' ') = '!'; % Nonprintable characters if url(end) == '/', url(end) = []; end % Look for links that should be skipped. skips = {'.gif','.jpg','.pdf','.css','lmscadsi','cybernet', ... 'search.cgi','.ram','www.w3.org', ... 'scripts','netscape','shockwave','webex','fansonly'}; skip = any(url=='!') | any(url=='?'); k = 0; while ~skip & (k < length(skips)) k = k+1; skip = ~isempty(findstr(url,skips{k})); end if skip if isempty(findstr(url,'.gif')) & isempty(findstr(url,'.jpg')) set(t2,'string',sprintf('skip: %s',url)) drawnow if get(slow,'value') pause(.25) end end continue end % Check if page is already in url list. i = 0; for k = find(hash(1:m) == hashfun(url))'; if isequal(U{k},url) i = k; break end end % Add a new url to the graph there if are fewer than n. if (i == 0) & (m < n) m = m+1; U{m} = url; hash(m) = hashfun(url); i = m; end % Add a new link. if i > 0 G(i,j) = 1; set(t2,'string',sprintf('%5d %s',i,url)) line(j,i,'marker','.','markersize',6) drawnow if get(slow,'value') pause(.25) end end end j = j+1; end delete(t1) delete(t2) delete(slow) set(quit,'string','close','callback','close(gcf)','value',0) %------------------------ function h = hashfun(url) % Almost unique numeric hash code for pages already visited. h = length(url) + 1024*sum(url); 

4.MapReduce框架下PageRank算法的实现

利用前面wiki上的迭代(或者幂法)的思想来实现MapReduce框架下PageRank算法很简单,可以先阅读下参考内容5。

这篇文章using-mapreduce-to-compute-pagerank更加详细,可以参考

以下是我的大数据的一次作业,要求是参考wiki上的简便算法,实现MapReduce框架下的PageRank算法。给的数据集是Twitter的用户之间的关系,可以看做是网页之间的关系,但是助教没要求写代码以及运行这个数据集(有1G多),所以下面只是一个Python版本的理想可行版本,并没有通过实际大数据集的验证,另外,博主暂时还不太会Python的mapreduce框架中的一些函数,所以实现的是一个简明的可以测试的PageRank算法。

1.输入输出格式

map函数的输入是<节点,从该节点引出的边列表>,其中节点是一个类,包含了其当前的pagerank值,输出是<节点,反向节点pagerank值/反向节点引出边的总数>;

reduce函数的输入是<节点,反向节点pagerank值/反向节点引出边的总数>,输出是<节点,从该节点引出的边列表>,其中节点包含了其更新后的pagerank值。

伪代码: [一时犯二写了个英文形式的 ]

process the data to the form of {node i:[its adjacent node list],...}
while the sum of difference between the last two pagerank values < thresholdmap({node i:[its adjacent node list],...}):map_output={}for every node j in adjacent node list: put or sum up {j:(i, PageRank(i)/length(adjacent node list))} into map_output return map_output reduce(map_output): reduce_output={} for every entry {j:(i, PageRank(i)/length(adjacent node list))} in map_output: put or sum up all values pagerank values for node j with its adjacent node list into reduce_output return reduce_output 

2.示例演示

假设用户1,2,3,4是如下图所示的关系:

image

假设有2个mapper(A和B)和1个reducer(C),初始时4个节点的pagerank值都是0.25

其中,关于用户1和2的数据被mapperA读取并处理,关于用户3和4的数据被mapperB读取并处理 [经验证,即使一个用户的数据是由不同的mapper来读取的,最终收敛到的结果差不多]

map的输入输出结果如下:

image

reduce的输入输出结果如下,输入是2个mapper的输出,输出的结果中更新了节点的pagerank值

image

reducer处理完了之后又将它的结果输入给mapper处理,直到迭代的次数超过了设定值或者两次迭代之后得到的所有节点的pagerank值之差的总和(也可以是取二范数)小于设定的阈值。

3.示例的实验结果

(1)首先是使用Matlab采用幂法的方式计算出在p=1.0的情况下示例得到的结果 [它的主要作用是验证后面python版本的正确性]

matlab源码如下:

n=4;
i=[2 3 4 3 4 4 1 2]; j=[1 1 1 2 2 3 3 4]; G=sparse(i,j,1,n,n); [n,n] = size(G); for j = 1:n L{j} = find(G(:,j)); c(j) = length(L{j}); end % Power method p=1.0; delta = (1-p)/n; x = ones(n,1)/n; z = zeros(n,1); cnt = 0; while max(abs(x-z)) > .0001 z = x; x = zeros(n,1); for j = 1:n if c(j) == 0 x = x + z(j)/n; else x(L{j}) = x(L{j}) + z(j)/c(j); end end x = p*x + delta; cnt = cnt+1; end sprintf('pagerank result:') x 

结果为:

0.1072
0.3571
0.2143
0.3214

(2)matlab版本的page rank没有采用mapreduce的思想进行迭代,所以我另外写了一个python版本的利用mapreduce思想实现的pagerank算法(注:我并没有使用python的map和reduce函数去实现,而是使用更加容易明白的实现),使用的阈值为0.0001,最多迭代的次数为100次。

# coding=utf-8__author__ = 'hujiawei'
__doc__ = 'pagerank mapreduce'class Node: def __init__(self,id,pk): self.id=id self.pk=pk def pk_map(map_input): map_output={} for node,outlinks in map_input.items(): for link in outlinks: size=len(outlinks) if link in map_output: map_output[link]+=(float)(node.pk)/size else: map_output[link]=(float)(node.pk)/size return map_output def pk_reduce(reduce_input): for result in reduce_input: for node,value in result.items(): node.pk+=value def pk_clear(nodes): for node in nodes: node.pk=0 def pk_last(nodes): lastnodes=[] for node in nodes: lastnodes.append(Node(node.id,node.pk)) return lastnodes def pk_diff(nodes,lastnodes): diff=0 for i in range(len(nodes)): print('node pk %f, last node pk %f ' % (nodes[i].pk, lastnodes[i].pk)) diff+=abs(nodes[i].pk-lastnodes[i].pk) return diff def pk_test1(): node1 = Node(1, 0.25) node2 = Node(2, 0.25) node3 = Node(3, 0.25) node4 = Node(4, 0.25) nodes = [node1, node2, node3, node4] threshold = 0.0001 max_iters = 100 for iter_count in range(max_iters): iter_count += 1 lastnodes=pk_last(nodes) print('============ map count %d =================' % (iter_count)) in1 = {node1: [node2, node3, node4], node2: [node3, node4]} in2 = {node3: [node1, node4], node4: [node2]} mapout1 = pk_map(in1) mapout2 = pk_map(in2) for node, value in mapout1.items(): print str(node.id) + ' ' + str(value) for node, value in mapout2.items(): print str(node.id) + ' ' + str(value) print('============ reduce count %d =================' % (iter_count)) reducein = [mapout1, mapout2] pk_clear(nodes) pk_reduce(reducein) for node in nodes: print str(node.id) + ' ' + str(node.pk) diff=pk_diff(nodes,lastnodes) if diff < threshold: break if __name__ == '__main__': pk_test1() 

得到的结果为如下,总共迭代了15次

1 0.107138774577
2 0.35712924859
3 0.214296601128
4 0.321435375705

上面的结果和Matlab用幂法得到的pagerank值差别很小,可以认为是正确的,所以说明了使用这种mapreduce输入输出格式的正确性。

OK,差不多了,希望对需要理解PageRank算法的人有帮助! :-)

转载于:https://www.cnblogs.com/ihongyan/p/4803720.html

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

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

相关文章

下面的语言中哪些语言是动态语言( )

下面的语言中哪些语言是动态语言(B ) A.C B.JavaScript C.C D.CSS E.Java F.Objective-C 解析 静态语言&#xff08;强类型语言&#xff09; 静态语言是在编译时变量的数据类型即可确定的语言&#xff0c;多数静态类型语言要求在使用变量之前必须声明数据类型。 例…

https://blog.csdn.net/weixin_40412037/article/details/112235003

一、工具简介 说明&#xff1a; 这是一款基于主机的漏洞扫描工具&#xff0c;采用多线程确保可以快速的请求数据&#xff0c;采用线程锁可以在向sqlite数据库中写入数据避免database is locked的错误&#xff0c;采用md5哈希算法确保数据不重复插入。 本工具查找是否有公开e…

前端工程师能力评估测试题(2020最新版附答案及解析)

1.下列哪个样式定义后,内联(非块状)元素可以定义宽度和高度 (C) A.display:inline B.display:none C.display:block D.display:inherit 解析 2.css属性overflow属性定义溢出元素内容区的内容会如何处理。如果值为 scroll,不论是否需要,用户代理都会提供一种滚动机…

埃氏筛法的一般写法(区间筛法)

问题&#xff1a; 求 $[L, R]$ 之间的素数表 解法&#xff1a; 一个合数 $n$ 的最小素因子不超过 $\sqrt{n}$。 先用埃氏筛法求出 $[1,\lfloor \sqrt{R} \rfloor]$ 上的素数表 再在 $[L, R]$ 上用埃氏筛法求素数 const int N(1e5); bool isprime[N]; int prime[N]; void init()…

滥用static_沉思滥用:“强力使用,破坏滥用”

滥用static前英国首相本杰明迪斯雷利&#xff08;Benjamin Disraeli&#xff09;曾用过一句古话&#xff0c;说这是三种谎言&#xff1a;“谎言&#xff0c;该死的谎言和统计数据”。 这里的暗示是&#xff0c;统计数字很容易弥补&#xff0c;因此不可靠。 但是&#xff0c;统计…

Cobalt strike加载插件出现乱码

问题描述 插件 加载成功出现乱码 解决方法 在Cobalt strike目录下执行命令指定编码打开客户端解决。 java -Dfile.encodingutf-8 -XX:ParallelGCThreads4 -XX:AggressiveHeap -XX:UseParallelGC -Xms512M -Xmx1024M -jar cobaltstrike.jar1 成功解决

新网站链接提交入口攻略

很多网站没有被收录,也没有排名,经常有SEO站长向我抱怨。其实提升网站收录有方法和诀窍的。下面我详细的为大家分享,如何向百度提交链接,提升网站被的机率。 很多新手站长,网站上线后没有主动的向搜索引擎提交,spider在短期内无法第一时间发现新网站,这个时候我们 需要…

MariaDb数据库管理系统的学习(一)安装示意图

MariaDB数据库管理系统是MySQL的一个分支。主要由开源社区在维护&#xff0c;採用GPL授权许可。开发这个分支的原因之中的一个是&#xff1a;甲骨文公司收购了MySQL后&#xff0c;有将MySQL闭源的潜在风险&#xff0c;因此社区採用分支的方式来避开这个风险。 MariaDB的目的是全…

内置序列化技术

本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题&#xff0c;包括对象创建&#xff0c;并发&#xff0c;序列化&#xff0c;反射等。 它将指导您完成Java掌握的过程&#xff01; 在这里查看 &#xff01; 目录 1.简…

初级前端工程师笔试技巧总结,祝你顺利拿高分

某大型外包公司安排新人去某大型保险公司驻场开发,简单粗暴的衡量一个工程师的水平就是笔试,这个环节是必不可少的,必须要过了笔试题才能算正式的驻场开发,不然只能是支持,消耗公司资源的废柴,一般笔试会有两次机会,我特殊情况考了三次,一套安全题(10题选择题共100分,…

HDU 5439 Aggregated Counting

题目大意&#xff1a; 由1开始不断往数组中添加数 就是按照当前所在位置所在的数表示的个数添加这个数目的数 1 2 2 3 3 后面因为要填4&#xff0c;而4号位置为3&#xff0c;说明之后要填3个4 问题就是给定一个n&#xff0c;找到n出现的最后位置p&#xff0c;再找p出现的最后位…

Ubuntu 安装msfconsole

Ubuntu 安装msfconsole 1.进入到opt目录下 cd /opt/1 2.下载安装文件 msfupdate.erb sudo wget https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb1 3.将文件msfupdate.erb重命名为msfinstal…

域名解析是否生效实时检测(阿里云DNS检测)

测试域名解析生效的方法有以下四类 域名解析生效测试本地域名解析生效测试测试命令dig或nslookup全国各地运营商解析生效测试域名解析生效测试 可帮助用户快速排查域名、DNS、网站问题,点击下方蓝色字体立即测试。 阿里云DNS检测 本地域名解析生效测试 此查询工具可以检测…

为什么需要多线程

对于这个问题可能很多朋友会说是为了高性能&#xff0c;个人觉得这是误解&#xff0c;多线程不等于高性能&#xff0c;从cpu&#xff08;单核&#xff09;的角度上看单线程才能带来最高性能。 对于单纯的运算任务来说一条线程依次执行到底肯定是最快速的&#xff08;因为线程间…

PhpMyAdmin后台getshell

PhpMyAdmin简介 PhpMyAdmin 是一个以PHP为基础&#xff0c;以Web-Base方式架构在网站主机上的MySQL的数据库管理工具&#xff0c;让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径&#xff0c;尤其要处理大量资料的汇入及汇出…

app mvc框架_Google App Engine上的Spring MVC和REST

app mvc框架前段时间&#xff0c;我写了一篇关于如何使用Spring MVC实现Restful Web API的文章 。 阅读我以前的文章以了解它。 在那篇文章中&#xff0c;它开发了一个简单的Rest示例。 为了测试该应用程序&#xff0c;将文件复制到Web服务器&#xff08;例如Tomcat &#xff0…

谷歌浏览器如何将繁体字设置成中文?

今天刚拿到公司发给我的电脑,这个电脑是戴尔的,不知道用了多少年啦,处理器是i3的,CPU8+50O还行,总体感觉一般,不卡顿,办公的地方网速跟蜗牛一样,整个电脑应该是重置过的或者重装了系统,作为开发下载常用的浏览器(谷歌、火狐、IE)、编译器、IM工具等还是很有必要的,…

Python学习笔记 -- 第一章

本笔记参考廖雪峰的Python教程 简介 Python是一种计算机高级程序设计语言. 用Python可以做什么&#xff1f; 可以做日常任务&#xff0c;比如自动备份你的MP3&#xff1b;可以做网站&#xff0c;很多著名的网站包括YouTube就是Python写的&#xff1b;可以做网络游戏的后台等等&…

红队技巧-域渗透的协议利用

1.pth(hash传递) 1.1 PTH简介 哈希传递(pth)攻击是指攻击者可以通过捕获密码的hash值(对应着密码的值),然后简单地将其传递来进行身份验证&#xff0c;以此来横向访问其他网络系统&#xff0c;攻击者无须通过解密hash值来获取明文密码&#xff0c;因为对于每个Session hash值都…

你这么喜欢敲代码,那么技术的乐趣在哪里?

在中国的技术圈子里,流行着这样一种说法:过了三十五岁,就一定得改行。在技术飞速发展的今天,只要稍不留神,就会掉下队来。因此,诸多技术工作者在仔细权衡利弊之后,终于还是决定跳离技术这个是非之地,将工作机会让给那些更青春更朝气的年轻一辈们。 当然,还是有相当一部…