爬虫入门讲解(用urllib库爬取数据 )

首先介绍说明什么是爬虫?

是一种按照一定的规则,自动地抓取互联网信息的程序或者脚本。 
所谓网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地。 在
Python中有很多库可以用来抓取网页 

爬虫分类 

通用爬虫(General Purpose Web Crawler)、 聚焦爬虫(Focused Web Crawler)、增量
式爬虫(Incremental Web Crawler)、深层爬虫(Deep Web Crawler) 

通用网络爬虫 
捜索引擎抓取系统(Baidu、Google、Yahoo 等)的重要组成部分。主要目的是将互联
网上的网页下载到本地,形成一个互联网内容的镜像备份。 

聚焦爬虫 
是"面向特定主题需求"的一种网络爬虫程序,它与通用搜索引擎爬虫的区别在于: 聚焦
爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息。
 增量式抓取 
是指在具有一定量规模的网络页面集合的基础上,采用更新数据的方式选取已有集合中的过时网页进行抓取,以保证所抓取到的数据与真实网络数据足够接近。进行增量式抓取的前提是,系统已经抓取了足够数量的网络页面,并具有这些页面被抓取的时间信息。  

深度爬虫 
针对起始url地址进行数据采集,在响应数据中进行数据筛选得到需要进行数据采集的下一波url地址,并将url地址添加到数据采集队列中进行二次爬取..以此类推,一致到所有页面的数据全部采集完成即可完成深度数据采集,这里的深度指的就是url地址的检索深度。

爬虫步骤 
网页抓取,数据提取,数据存储 

HTTP协议 
HTTP,HyperText Transfer Protocol,是互联网上应用最为广泛的一种网络协议。 
是一个基于TCP/IP通信协议来传递数据,一个属于应用层的协议 
浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服
务器根据接收到的请求后,向客户端发送响应信息。 
HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)HTTP的安全版,在
HTTP下加入SSL层。 
SSL(Secure Sockets Layer 安全套接层)主要用于Web的安全传输协议,在传输层对网
络连接进行加密,保障在Internet上数据传输的安全。 

HTTP 的端口号为 80, 
HTTPS 的端口号为 443 。

urlib的使用 

在Python3.x中,我们可以使用urlib这个组件抓取网页,urllib是一个URL处理包,这个
包中集合了一些处理URL的模块 
1.urllib.request模块是用来打开和读取URLs的; 
2.urllib.error模块包含一些有urllib.request产生的错误,可以使用try进行捕捉处理; 
3.urllib.parse模块包含了一些解析URLs的方法; 
4.urllib.robotparser模块用来解析robots.txt文本文件.它提供了一个单独的RobotFileP
arser类,通过该类提供的can_fetch()方法测试爬虫是否可以下载一个页面。 

urllib.request.urlopen() 

这个接口函数就可以很轻松的打开一个网站,读取并打印信息。 
from urllib import request 
 
if __name__ == "__main__": 
    response = request.urlopen("http://fanyi.baidu.com") 
    html = response.read() 
print(html) 
说明 
request.urlopen()打开和读取URLs信息,返回对象response 

自动获取网页编码

chardet 
第三方库,用来判断编码的模块 
使用chardet.detect()方法,判断网页的编码方式 
安装方法: 
pip install chardet 
代码: 
from urllib import request 
import chardet 
if __name__ == "__main__": 
    response = request.urlopen("http://fanyi.baidu.com/") 
    html = response.read() 
    charset = chardet.detect(html) 
    print(charset) 

Request对象 

反爬虫机制: 
1、 封杀爬虫程序 
2、 封杀指定IP 
3、 封杀非人操作的程序 

如果需要执行更复杂的操作,比如增加 HTTP 报头,必须创建一个 Request 实例来作为
urlopen()的参数;而需要访问的 url 地址则作为 Request 实例的参数。 
from urllib import request 
 
if __name__ == "__main__":     req = request.Request("http://fanyi.baidu.com/")    

response = request.urlopen(req) 

 html = response.read()    

html = html.decode("utf-8") print(html) 

User Agent 
浏览器就是互联网世界上公认被允许的身份,如果我们希望我们的爬虫程序更像一个真
实用户,那我们第一步,就是需要伪装成一个被公认的浏览器。用不同的浏览器在发送
请求的时候,会有不同的 User-Agent 头。中文名为用户代理,简称UA 
User Agent存放于Headers中 
服务器就是通过查看Headers中的User Agent来判断是谁在访问。 
urllib中默认的User Agent,会有Python的字样,如果服务器检查User Agent,可以拒
绝Python程序访问网站。 

设置User Agent 
方法 1:在创建 Request 对象的时候,填入 headers 参数(包含 User Agent 信息),这个
Headers参数要求为字典; 
方法2:在创建Request对象的时候不添加headers参数,在创建完成之后,使用add_h
eader()的方法,添加headers。 

from urllib import request

if __name__ == "__main__":
    url = 'http://www.csdn.net/'
    head = {}  # 写入 User Agent 信息
    head['User-Agent'] = 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19'
    #创建 Request 对象
    req = request.Request(url, headers=head)
    # 也可以通过调用Request.add_header()添加/修改一个特定的 header
    req.add_header("User-Agent", "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19")
    req.add_header("Connection", "keep-alive")
    # 也可以通过调用 Request.get_header()来查看 header 信息
    print(req.get_header(header_name="Connection"))
    print(req.get_header(header_name="User-Agent"))
    # #传入创建好的 Request 对象
    response = request.urlopen(req)
    # #读取响应信息并解码
    html = response.read().decode('utf-8')
    # #打印信息
    print(html)

IP代理 
直接访问网站 
python

代理分类 
代理可以分为三种,即高度匿名代理、普通匿名代理和透明代理。 
高度匿名代理 隐藏客户的真实IP,但是不改变客户机的请求,就像有个真正的客户浏览器
在访问服务器。 
普通匿名代理 能隐藏客户机的真实 IP,会改变客户的请求信息,服务器端不知道你的 ip
地址但有可能认为我们使用了代理。 
透明代理 不但改变了我们的请求信息,还会传送真实的IP地址。 
 
爬虫程序运行速度是很快,在网站爬取数据时,一个固定IP的访问频率就会很高,这不符合
人为操作的标准。所以一些网站会设置一个IP访问频率的阈值,如果一个IP访问频率超过
这个阈值,说明这个不是人在访问,而是一个爬虫程序。 
解决办法一:设置延时 
解决办法二:使用 IP 代理。可以设置一些代理服务器,每隔一段时间换一个代理,就算 IP
被禁止,依然可以换个IP继续爬取。 
免费短期代理网站举例: 
西刺免费代理IP   http://www.xicidaili.com/ 
快代理免费代理   http://www.kuaidaili.com/free/inha/ 
聚合数据 https://www.juhe.cn/docs/api/id/62 
代理IP选取 
西刺网站为例,选出信号好的IP 

使用代理的步骤: 
 (1)调用urlib.request.ProxyHandler(),构建处理器对象,proxies参数为一个字典。 
 
   (2)创建Opener对象 
 
 (3)安装Opener 
 
使用 install_opener 方法之后,会将程序默认的 urlopen 方法替换掉。也就是说,如果使
用install_opener之后,在该文件中,再次调用urlopen会使用自己创建好的opener。 

url编码解码 
urllib.parse.urlencode()函数帮我们将key:value这样的键值对转换成"key=value"这样的
的字符串,解码工作可以使用urllib的unquote()函数。 
from urllib import parse word = {"title" : "天猫商城"} url1 = parse.urlencode(word) print(url1) url2 =parse.unquote(url1) print(url2) 

GET请求 
GET 请求一般用于向服务器获取数据 
案例:百度搜索端午节 

在其中可以看到在请求部分里,http://www.baidu.com/s? 之后出现一个长长的字符串,
其中就包含我们要查询的关键词,于是我们可以尝试用默认的 Get 方式来发送请求。 

POST请求 
urlopen的data参数,是POST方法进行Request请求时,要传送给服务器的数据,字典
类型,里面要匹配键值对。 
如果没有设置urlopen()函数的data参数,HTTP请求采用GET方式 
使用urllib.parse.urlencode()函数将发送的表单数据编码 

Cookie 
HTTP是无状态的面向连接的协议, 为了保持连接状态, 引入了Cookie机制, 在浏览器中存
储用户信息 
应用:Cookie模拟登陆 
# 获取一个有登录信息的 Cookie 模拟登陆 from urllib import request import chardet 
 
# 1. 构建一个已经登录过的用户的 headers 信息

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

"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",    

# 便于终端阅读,表示不支持压缩文件    

# Accept-Encoding: gzip, deflate, sdch,  

"Accept-Language":"zh-CN,zh;q=0.9",     "Cache-Control": "max-age=0",     "Connection":"keep-alive",     # 重点:这个 Cookie 是保存了密码无需重复登录的用户的 Cookie,这个 Cookie 里记录 了用户名,密码(通常经过 RAS 加密)     "Cookie": "__cfduid=d813c9add816556c64a8c087554cfb7af1508468882; BDUSS=kM2UnphaUpJRVphdjFrQ3R0TX5KM1NhY25mLVFmdTUtbTJ2ZndiMkw1TWRYRkJiQUFBQ UFBJCQAAAAAAAAAAAEAAABUN0cMVG9temt5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3PKFsdzyhba; BAIDUID=675B04E847A8A586ECC76203C511EA12:FG=1; PSTM=1529894757; BD_UPN=12314753; BIDUPSID=269D2DF8A150308A1A953FED45517BA8; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BD_CK_SAM=1; PSINO=1; H_PS_PSSID=1428_21106_20927; BD_HOME=1",     "Host":"www.baidu.com",     "Upgrade-Insecure-Requests":"1", } 
 
# 2. 通过 headers 里的报头信息(主要是 Cookie 信息),构建 Request 对象 req = request.Request("https://www.baidu.com/", headers = headers) 
 
# 3. 直接访问 renren 主页,服务器会根据 headers 报头信息(主要是 Cookie 信息),判断这 是一个已经登录的用户,并返回相应的页面 response = request.urlopen(req) # 4. 打印响应内容 html = response.read() charset = chardet.detect(html)['encoding'] print(charset) print(html.decode(charset)) 
 
cookielib库 和 HTTPCookieProcessor处理器 
Python 处理 Cookie,一般是通过 cookielib 模块和 urllib 的 request 模块的
HTTPCookieProcessor处理器类一起使用。 
cookielib模块:主要作用是提供用于存储cookie的对象 
HTTPCookieProcessor处理器:主要处理cookie对象,并构建handler对象。 

cookielib 库 
主要作用是提供用于存储cookie的对象 
该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。 
CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie 的对象。整个 cookie 都存储在内存中。 FileCookieJar (filename,delayload=None,policy=None):CookieJar 派生而来,将 cookie 存储到 文件中。filename 是存储 cookie 的文件名。delayload 为 True 时支持延迟访问文件,即只有 在需要时才读取文件或在文件中存储数据。 MozillaCookieJar (filename,delayload=None,policy=None) :从 FileCookieJar 派 生 而 来 , MozillaCookieJar 实例与 Mozilla 浏览器 cookies.txt 兼容。 LWPCookieJar (filename,delayload=None,policy=None):从 FileCookieJar 派生而来,实例与 libwww-perl 标准的 Set-Cookie3 文件格式兼容。 
HTTPCookieProcessor处理器:处理cookie对象,并构建handler处理器对象。 
案例:获取Cookie,生成CookieJar()对象中 
from urllib import request import http.cookiejar 
 
# 构建一个 CookieJar 对象实例来保存 cookie cookiejar = http.cookiejar.CookieJar() 
 
# 使用 HTTPCookieProcessor()来创建 cookie 处理器对象,参数为 CookieJar()对象 handler=request.HTTPCookieProcessor(cookiejar) 
 
# 通过 build_opener() 来构建 opener opener = request.build_opener(handler) 
 
# 4. 以 get 方法访问页面,访问之后会自动保存 cookie 到 cookiejar 中 opener.open("https://www.baidu.com") 
 
## 可以按标准格式将保存的 Cookie 打印出来 cookieStr = "" for item in cookiejar:     cookieStr = cookieStr + item.name + "=" + item.value + ";" 
 
## 舍去最后一位的分号 print(cookieStr[:-1]) 

获取AJAX加载的内容 
AJAX一般返回的是JSON,直接对AJAX地址进行post或get,就返回JSON数据了。 

from urllib import request from urllib import parse 
 
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action" headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"} # 变动的是这两个参数,从 start 开始往后显示 limit 个 formdata = {     'start':'0',     'limit':'10' } data = parse.urlencode(formdata).encode(encoding='UTF8') req = request.Request(url, data = data, headers = headers) response = request.urlopen(req) print(response.read().decode('utf-8')) 
 
HTTPS请求 SSL证书验证 
现在随处可见 https 开头的网站,urllib2 可以为 HTTPS 请求验证 SSL 证书,就像 web
浏览器一样,如果网站的 SSL 证书是经过 CA 认证的,则能够正常访问,如:
https://www.baidu.com/等... 
如果 SSL 证书验证不通过,或者操作系统不信任服务器的安全证书,比如浏览器在访问
12306 网站如:https://www.12306.cn/mormhweb/的时候,会警告用户证书不受信任。
(据说 12306 网站证书是自己做的,没有通过CA 认证) 

urllib.error 
urllib.error可以接收有urllib.request产生的异常。 
 
URLError 
产生的原因主要有: 
 没有网络连接 
 服务器连接失败 
 找不到指定的服务器 
案例:访问了一个不存在的域名,用try except语句来捕获相应的异常 
from urllib import request from urllib import error 
 
if __name__ == "__main__":    

#一个不存在的连接    

url = "http://www.ajkfhafwjqh.com/"    

req = request.Request(url) 

 try:        

response = request.urlopen(req)        

html = response.read().decode('utf-8')        

print(html)    

except error.URLError as e:        

print(e.reason) 
HTTPError 
HTTPError 是 URLError 的子类,我们发出一个请求时,服务器上都会对应一个 response
应答对象,其中它包含一个数字"响应状态码"。 
如果 urlopen 不能处理的,会产生一个 HTTPError,对应相应的状态码,HTTP 状态码表
示HTTP协议所返回的响应的状态。 
from urllib import request from urllib import error 
 
if __name__ == "__main__":    

#一个不存在的连接    

url = "http://www.zhihu.com/AAA.html"    

#url = "http://blog.csdn.net/cqcre"    

req = request.Request(url)    

try:        

responese = request.urlopen(req)        

html = responese.read()        

print(html)    

except error.HTTPError as e:        

print(e.code) 

混合使用 
如果想用 HTTPError 和 URLError 一起捕获异常,那么需要将 HTTPError 放在 URLError
的前面,因为HTTPError是URLError的一个子类。如果URLError放在前面,出现HTTP
异常会先响应URLError,这样HTTPError就捕获不到错误信息了。 
from urllib import request from urllib import error 
 
req = request.Request("http://www.douyu.com/tom_kwok.html") try:     request.urlopen(req) except error.HTTPError as err:     print(err.code) except error.URLError as err:     print(err) else:     print("Good Job") 
也可以使用hasattr函数判断一场对象含有的属性,如果含有reason属性表明是URLError,
如果含有code属性表明是HTTPError。 
if __name__ == "__main__":    

#一个不存在的连接     url = "http://www.douyu.com/tom_kwok.html"    

req = request.Request(url)    

try:        

responese = request.urlopen(req)    

except error.URLError as e:        

if hasattr(e, 'code'):            

print("HTTPError")            

print(e.code)        

elif hasattr(e, 'reason'): 

 print("URLError")            

print(e.reason) 
状态码 
状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值: 
1xx:指示信息–表示请求已接收,继续处理

2xx:成功–表示请求已被成功接收、理解、接受

3xx:重定向–要完成请求必须进行更进一步的操作

4xx:客户端错误–请求有语法错误或请求无法实现 5xx:服务器端错误–服务器未能实现合法的请求

常见状态代码、状态描述、说明: 200 OK     //客户端请求成功 400 Bad Request  //客户端请求有语法错误,不能被服务器所理解 401 Unauthorized //请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用 403 Forbidden  //服务器收到请求,但是拒绝提供服务 404 Not Found  //请求资源不存在,eg:输入了错误的 URL 500 Internal Server Error //服务器发生不可预期的错误 503 Server Unavailable  //服务器当前不能处理客户端的请求,一段时间后可能恢复正常 

猜你喜欢

转载自blog.csdn.net/lzz781699880/article/details/81587978
今日推荐