欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python网络爬虫学习(一)

程序员文章站 2022-05-08 17:41:15
...

网络爬虫的定义:

一个程序脚本--->自动的抓取互联网上信息的脚本。

爬虫可以解决的问题:

(1)解决冷启动问题。
(2)搜索引擎的根基:做搜索引擎少不了爬虫。
(3)建立知识图谱,帮助建立机器学习知识图谱。
(4)可以制作各种商品的比价软件,趋势分析。

爬虫工程师的进阶之路

1.初级爬虫工程师:

1.web 前端的知识: HTML、CSS、JavaSc1ipt、 DOM、 DHTML 、Ajax、jQuery、json 等;
2、正则表达式, 能提取正常一般网页中想要的信息,比如某些特殊的文字, 链接信息, 知道什么是懒惰, 什么是贪婪型的正则;
3、会使用 XPath 等获取一些DOM 结构中的节点信息;
4、知道什么是深度优先, 广度优先的抓取算法, 及实践中的使用规则;
5、能分析简单网站的结构, 会使用urllib或requests 库进行简单的数据抓取。

2.中级爬虫工程师:

1、了解什么是HASH,会简单地使用MD5,SHA1等算法对数据进行HASH一遍存储
2、熟悉HTTP,HTTPS协议的基础知识,了解GET,POST方法,了解HTTP头中的信息,包括返回状态码,编码,user-agent,cookie,session等
3、能设置user-agent进行数据爬取,设置代理等
4、知道什么是Request,什么事response,会使用Fiddler等工具抓取及分析简单地网络数据包;
   对于动态爬虫,要学会分析ajax请求,模拟制造post数据包请求,
   抓取客户端session等信息,对于一些简单的网站,能够通过模拟数据包进行自动登录。
5、对于一些难搞定的网站学会使用phantomjs+selenium抓取一些动态网页信息
6、并发下载,通过并行下载加速数据爬取;多线程的使用。

3.高级爬虫工程师:

1、能够使用Tesseract,百度AI,HOG+SVM,CNN等库进行验证码识别。
2、能使用数据挖掘技术,分类算法等避免死链。
3、会使用常用的数据库进行数据存储,查询。比如mongoDB,redis;学习如何通过缓存避免重复下载的问题。
4、能够使用机器学习的技术动态调整爬虫的爬取策略,从而避免被禁IP封禁等。
   能使用一些开源框架scrapy,scrapy-redis等分布式爬虫,
   能部署掌控分布式爬虫进行大规模数据爬取。

搜索引擎:

1.搜索引擎的主要组成:
	通用爬虫:就是将互联网的上页面整体的爬取下来之后,保存到本地。
		 1.通用爬虫要想爬取网页,需要网站的url.但是搜索引擎是可以搜索所有网页的。
		   那么通用爬虫url就要涉及到所有网页,这个‘所有’是如何做到的。
			1.新网站向搜索引擎主动提交网址
			2.在其他网站上设置新网站外链。
			3、搜索引擎和DNS解析服务商(如DNSPod等)合作,新网站域名将被迅速抓取。
2.搜索引擎的工作流程:
	第一步:抓取网页
		通过将待爬取的url加入到通用爬虫的url队列中,进行网页内容的爬取。
		
	第二步:数据存储:
		将爬取下来网页保存到本地。这个过程中会有一定的去重操作。如果某个网页的内容大部分重复,搜索引擎可能不会保存。
		
	第三步:预处理
		提取文字
		中文分词
		消除噪音(比如版权声明文字、导航条、广告等……)
		索引处理
	第四步:设置网站排名,为用户提供检索服务。
		
3.搜索引擎的局限性:
	1、搜索引擎只能爬取原网页,但是页面90%内容都是无用的。
	2、搜素引擎不能满足不同行业,不同员的特定需求。
	3、通用搜索引擎只能爬取文字信息,对于视频,文件,音频等其他信息无法爬取。
	4、只能基于关键字查询,无法基于语义查询。

聚焦爬虫:聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需相关的网页信息。

爬虫准备工作:

1.robots协议
	定义:网络爬虫排除标准
	作用:告诉搜索引擎哪些内容可以爬,哪些不能爬。
2、sitemap,就是一个网站地图,可以指导我们查看该网页下有哪些内容。
	https://help.bj.cn/
3、估算网站大小:
	在百度中输入:site:目标网站的地址。
4、为了更好的了解网站,抓取该网站的信息,我们可以先了解一下该网站大致所使用的的技术架构。
	安装builtwith:pip install bulitwith
	使用:在python交互环境下,输入:
	Import buildwith
	Buildwith.parse(‘http://www.sina.com.cn’)
5、有时候,我们需要知道网站的所有者是谁,这里在技术上有个简单地方法可以参考:
	安装python-whois:pip install python-whois
	使python的交互模式下输入:
	Import whois
	Whois.whois(‘http://www.sina.com.cn’)

http和https:

1、什么是http协议?
	http:超文本传输协议
	他是一个规范。----约束发布和接收html页面的规范。
	HTTPS (Hypertext Transfer Protocol over Secure Socket Layer)简单讲是http的安全版,在http下加入SSL层
2.http协议的端口号:80
  https协议的端口号:443
3、http协议的特点:
	(1)是一个应用层协议。
	(2)无连接
		每次请求都是独立的。
		http 1.1 增加了一个Connection: keep-alive,这个头表示,客户端和服务器的连接是一个长连接。
	(3)无状态。
		无状态表示客户端每次请求都不能记录请求状态。也就是两条请求之间无法进行通信。
		cookie和session可以帮助记录状态。

4、url:统一资源定位符。
	为什么可以通过url来定位互联网上的任意资源?
	http://ip:port/path
	ip:可以定位电脑
	port:端口号---用来从互联网上进入电脑。
	path:就是为了在电脑中找到对应的资源路径。
	
	有三种特殊符号
	?:问好后面就是请求参数。?username='zhangsan'&password='123'
	&:请求参数用&连结。?username='zhangsan'&password='123'
	#:表示锚点:锚点就是在请求这个url时,页面会跳入锚点指定位置。
	
	基本格式:scheme://host[:port#]/path/…/[?query-string][#anchor]
	scheme:协议(例如:http, http, ftp)
	host:服务器的IP地址或者域名
	port:服务器的端口(如果是走协议默认端口,缺省端口80)
	path:访问资源的路径
	query-string:参数,发送给http服务器的数据
	anchor:锚(跳转到网页的指定锚点位置)
	
	在python中,有一个模块可以帮助我们解析url。
	代码:
		from urllib import parse

		url = 'http://localhost.com:8080/index.htm?username="zhangsan"&password="123"'
		print(parse.urlparse(url))
	输入内容:
		ParseResult(
			scheme='http', 
			netloc='localhost.com:8080', 
			path='/index.htm', 
			params='', 
			query='', 
			fragment='')
5、http工作过程
  (1)地址解析,将url解析出对应的内容:
		
	  scheme:协议(例如:http, http, ftp)
	host:服务器的IP地址或者域名
	port:服务器的端口(如果是走协议默认端口,缺省端口80)
	path:访问资源的路径
	query-string:参数,发送给http服务器的数据
	anchor:锚(跳转到网页的指定锚点位置)
   (2)封装http请求数据包
   (3)封装成TCP包,建立TCP连接(TCP的三次握手)
		TCP握手协议 
		第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; 
		SYN:同步序列编号(Synchronize Sequence Numbers)
		第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),
		同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 
		第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),
		此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
		完成三次握手,客户端与服务器开始传送数据
		
	(4)客户端发送请求。
	(5)服务器发送响应。
	(6)服务器关闭tcp连接。
6、当我们在浏览器输入一个url,为什么可以加载出一个页面?
   为什么,在抓包的过程中,请求了一个url,会出现很多的资源请求。
	(1)当我们在浏览器输入一个url,客户端会发送这个url对应的一个请求到指定服务器获取内容。
	(2)服务器收到这个请求,解析出对应的内容,之后将内容封装到响应里面发送给客户端。
	比如index.html页面。
	(3)当客户端拿到这个html页面,会查看这个页面中是否有css、js、image等url,如果有,在分别进行请求,获取到这些资源。
	(4)客户端会通过html的语法,将获取到的所有内容完美的显示出来。
7、客户端请求:
	(1)组成:请求行、请求头部、空行、请求数据四个部分组成
	 (2) 请求方法get/post
		1、get方法:
		 get,获取--->从服务器上获取资源--->通过请求参数来告诉服务器获取什么资源。
		 --->请求参数是在url里面用&进行拼接的,也就是?后面的内容。---->所以不安全--->传输参数大小受限。
		2、post请求:
			post,传递--->向服务器传递数据---->数据是封装在请求的实体。--->可以传递更多内容--->更安全。
	    3、get和post的区别
			(1)get是从服务器获取内容,post是向服务器传递内容
			(2)get不安全,因为参数拼接在url后面。post比较安全,因为参数是放在是实体里面。
			(3)get传参大小受限,post不受限。
		 
	(3)重要的请求头:
		User-Agent:客户端请求标识。
		Accept: (传输文件类型)允许传入的文件类型。
		Referer :表明产生请求的网页来自于哪个URL,用户是从该Referer页面访问到当前请求的页面。
		cookie (cookie):在做登录的时候需要封装这个头。
		Content-Type (POST数据类型)
		
		发送POST请求时,需要特别注意headers的一些属性:
		Content-Length: 144: 是指发送的表单数据长度为144,也就是字符个数是144个。
		X-Requested-With: XMLhttpRequest :表示Ajax异步请求。
		
8、服务响应
	1、组成:状态行,响应头,空行,响应正文。
	2、重要响应头:
		Content-Type:text/html;charset=UTF-8:告诉客户端,资源文件的类型,还有字符编码
		
	3、状态码:
		100~199:表示服务器成功接收部分请求,要求客户端继续提交其余请求才能完成整个处理过程。
		200~299:表示服务器成功接收请求并已完成整个处理过程。常用200(OK 请求成功)。				
		300~399:为完成请求,客户需进一步细化请求。
		例如:请求的资源已经移动一个新地址、常用302(所请求的页面已经临时转移至新的url)、307和304(使用缓存资源)。
		400~499:客户端的请求有错误,常用404(服务器无法找到被请求的页面)、403(服 务器拒绝访问,权限不够---DDos)。
		500~599:服务器端出现错误,常用500(请求未完成。服务器遇到不可预知的情况)。

Hash算法

1、定义
    Hash :散列,通过关于键值(key)的函数,将数据映射到内存存储中一个位置来访问。这个过程叫做Hash,这个映射函数称做散列函数,存放记录的数组称做散列表(Hash Table),又叫哈希表。

    简单地说,它是密码学中的一个重要的函数,一般以

	表示。这个函数可以将任意一段数据(一般称这段数据为“消息”)压缩成固定长度的字符串(一般称输出的字符串为“摘要”)。哈希函数需要满足下述条件:
	确定性:哈希函数的算法是确定性算法,算法执行过程不引入任何随机量。这意味着相同消息的哈希结果一定相同。
	高效性:给定任意一个消息m,可以快速计算
	
	
	目标抗碰撞性:给定任意一个消息m1,很难找到另一个消息m2,使得
	
	
	广义抗碰撞性:很难找到两个消息m0不等于m1的情况下,使得


2、优点
    先分类,再查找,通过计算,缩小范围,加快查找速度
3、Hash的作用
	数字签名:给数据打指纹
		比如我们下载一个文件,文件的下载过程中会经过很多网络服务器、路由器的中转,
		如何保证这个文件就是我们所需要的呢?
		我们不可能去一一检测这个文件的每个字节,
		也不能简单地利用文件名、文件大小这些极容易伪装的信息,
		这时候,我们就需要一种指纹一样的标志来检查文件的可靠性,
		这种指纹就是我们现在所用的Hash算法(也叫散列算法)。
		
	密码存储:在用户进行网站登录时,如果服务器直接存储用户密码,则如果服务器被攻击者所攻击,用户的密码就会遭到泄露。
		最典型的事件就是CSDN的密码明文存储事件了。
		为了解决这个问题,服务器可以仅存储用户密码的哈希结果。
		当用户输入登录信息后,服务器端可以计算密码的哈希结果,
		并与存储的哈希结果进行对比,如果结果相同,则允许用户登录。
		由于服务器不直接存储用户密码,因此即使服务器被攻击者攻击,用户的密码也不会被泄露。
		这也是为什么我们在使用【找回密码】功能时,服务器直接请求输入新的密码,
		而不是把原始密码发送给我们。

4、hash算法的特性
	正向快速:给定明文和 hash 算法,在有限时间和有限资源内能计算出 hash 值。
	逆向困难:给定(若干) hash 值,在有限时间内很难(基本不可能)逆推出明文。
	输入敏感:原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。
	冲突避免:很难找到两段内容不同的明文,使得它们的 hash 值一致(发生冲突)。即对于任意两个不同的数据块,
	其hash值相同的可能性极小;对于一个给定的数据块,找到和它hash值相同的数据块极为困难。
	所以因为他的不可逆性,hash算法常常用来给一些信息加密,因为这种不可逆性,
	你不仅不可能根据一段通过散列算法得到的指纹来获得原有的文件,
	也不可能简单地创造一个文件并让它的指纹与一段目标指纹相一致。
5、hash算法(了解)
 (1)直接定值法:取Key或者Key的某个线性函数值为散列地址。
 (2)数字分析法:需要知道Key的集合,并且Key的位数比地址位数多,选择Key数字分布均匀的位。
	Hash(Key) 取六位:
	列数 : 1   (2)   3   (4)   5   (6)   (7)   8   (9)   10   11   12   (13)
	key1:  5    2    4    2    7    5     8     5     3     6     5     1      3
	key2:  5    4    4    8    7    7     7     5     4     8     9     5      1
	key3:  3    1    5    3    7    8    5      4     6     3      5     5     2
	key4:  5    3    6    4    3    2      5    4     5      3      2    6     4
	
	其中(2、4、6、7、9、13) 这6列数字无重复,分布较均匀,取此六列作为Hash(Key)的值。
	Hash(Key1) :225833
	Hash(Key2):487741
	Hash(Key3):138562
	Hash(Key4):342554
	
	(3)平方取中法:取Key平方值的中间几位作为Hash地址。
	(4)折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后 取这几部分的叠加和(舍去进位)作为哈希地址。 
		当Key的位数较多的时候数字分布均匀适合采用这种方案.
	(5)随机数法:伪随机探测再散列。
	    具体实现:建立一个伪随机数发生器,Hash(Key) = random(Key). 以此伪随机数作为哈希地址。
	(6)除留余数法:取关键字被某个除数 p 求余,得到的作为散列地址。
	    即 H(Key) = Key % p;
	6、Hash有哪些流行的算法
	目前流行的 Hash 算法包括 MD5、SHA-1 和 SHA-2。
	
	MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的,
	MD 是 Message Digest 的缩写。其输出为 128 位。MD4 已证明不够安全。
	
	MD5(RFC 1321)是 Rivest 于1991年对 MD4 的改进版本。
	它对输入仍以 512 位分组,其输出是 128 位。MD5 比 MD4 复杂,
	并且计算速度要慢一点,更安全一些。MD5 已被证明不具备”强抗碰撞性”。
	
	SHA (Secure Hash Algorithm)是一个 Hash 函数族,
	由 NIST(National Institute of Standards and Technology)于 1993 年发布第一个算法。
	目前知名的 SHA-1 在 1995 年面世,它的输出为长度 160 位的 hash 值,因此抗穷举性更好。
	SHA-1 设计时基于和 MD4 相同原理,并且模仿了该算法。SHA-1 已被证明不具”强抗碰撞性”。
	
	为了提高安全性,NIST 还设计出了 SHA-224、SHA-256、SHA-384,和 SHA-512 算法(统称为 SHA-2),
	跟 SHA-1 算法原理类似。SHA-3 相关算法也已被提出。

7、何谓Hash算法的「碰撞」?
    如果两个key通过hash函数处理之后得到的散列值相同,这种情况就叫做散列算法的碰撞(collision)。
    现代散列算法所存在的理由就是,它的不可逆性能在较大概率上得到实现,
    也就是说,发现碰撞的概率很小,这种碰撞能被利用的概率更小。
    7.1MD5碰撞案例
	import hashlib

	两段HEX字节串,注意它们有细微差别
	a = bytearray.fromhex("0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef")

	b = bytearray.fromhex("0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef")

 	输出MD5,它们的结果一致
	print(hashlib.md5(a).hexdigest())
	print(hashlib.md5(b).hexdigest())

    这样的例子还有很多。因此,MD5在数年前就已经不被推荐作为应用中的散列算法方案,取代它的是SHA家族算法,
    也就是安全散列算法(Secure Hash Algorithm,缩写为SHA)。
    7.2 	SHA家族算法以及SHA1碰撞
    SHA家族算法的种类很多,有SHA0、SHA1、SHA256、SHA384等等,它们的计算方式和计算速度都有差别。
    其中SHA1是现在用途最广泛的一种算法。
    包括GitHub在内的众多版本控制工具以及各种云同步服务都是用SHA1来区别文件,
    很多安全证书或是签名也使用SHA1来保证唯一性。
    长期以来,人们都认为SHA1是十分安全的,至少大家还没有找到一次碰撞案例。