# 爬虫
- 两大特征
- 按做者要求下载数据或者内容
- 能自动在网络上流窜
- 三大步骤
- 下载网页
- 提取正确的信息
- 根据必定规则自动跳转到另外的网页上执行
- 爬虫分类
- 通用爬虫
- 专用爬虫(聚焦爬虫)
- Python网络包简介
- Python2.x:urllib, urllib2, urllib3, httplib, httplib2, requests
- Python3.x:urllib, urllib3, httplib2, requests
- Python2:urllib和urllib2配合使用,或者requests
- Python3:urllib, requests
- urllib
- 包含模块
- urllib.request:打开和读取url
- urllib.error:包含urllib.requests产生的常见的错误,使用try捕捉
- urllib.parse:包含解析url方法(字典性的数据做为参数使用)
- urllib.robotparse:解析robots.txt文件
- 案例v1
- 网页编码问题解决
- chardet:能够自动检测页面文件的编码格式,可是,可能有误
- 须要先安装:conda install chardet
- 案例v2
- urlopen的返回对象
- 案例v3
- geturl:返回请求对象的url
- info:请求反馈对象的meta信息
- getcode:返回的http code
- request.data的使用
- 访问网络的两种方法
- get
- 利用参数给服务器传递信息
- 参数为dict格式,而后用parse编码
- 案例v4
- post
- 通常向服务器传递参数使用
- post是把信息自动加密处理
- 咱们若是想使用post方式传递信息,须要用到data参数
- 使用post意味着Http的请求头可能须要更改:
- Content-Type:application/x-www.form-urlencode
- Content-Length:数据长度
- 简而言之,一旦更改请求方法,请注意其余请求头部信息相适应
- urllib.parse.urlencode能够将字符串自动转换成上面的
- 案例v5
- 为了更多的设置请求信息,单纯的经过urlopen已经不太好用了
- 须要利用request.Request类
- 案例v6
- urllib.error
- URLError产生缘由:
- 没网
- 服务器连接失败
- 找不到指定服务器
- 自己是OSError的子类
- 案例v7
- HTTPError是URLError的一个子类
- 案例v8
- 二者区别:
- HTTPError是对应的HTTP请求的返回码错误,若是返回错误码是400以上,则引起HTTPError
- URLError对应的通常是网络出现问题,包括url错误
- 关系区别:OSError-URLError-HTTPError
- UserAgent
- UserAgent:用户代理,简称UA,属于headers的一部分,服务器经过UA来判断访问者的身份
- 常见的UA值,使用的时候能够直接复制粘贴,也能够用浏览器访问的时候抓包
- 目前有Android、Firefox、Google Chrome、ios的UA
- 这个是例子:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
- 设置UA能够经过两种方式
- headers
- add_header
- 案例v9
- ProxyHandler处理(代理服务器)
- 使用代理IP,是爬虫的经常使用手段
- 获取代理服务器的地址
- www.xicidaili.com
- www.goubanjia.com
- 代理用来隐藏真实访问地址,代理也不容许频繁访问某一个固定网站,因此,代理必定要不少不少
- 基本使用步骤:
一、设置代理地址
二、建立ProxyHandler
三、建立Opener
四、安装Opener
- 案例v10
- cookie & session
- 因为http协议的无状态性(无记忆性),人们为了弥补这个缺憾,所采用的一个补充协议
- cookie是发给用户(即http浏览器)的一段信息;session是保存在服务器上的对应另外一半的信息,用来记录用户信息
- cookie和session区别:
- 存放位置不用
- cookie不安全
- session会保存在服务器上必定时间,会过时
- 单个cookie保存数据不超过4K,不少浏览器限制一个站点最多保存20个
- session的存放位置
- 存在服务器端
- 通常状况,session是放在内存中或者数据库中
- 没有cookie登录,案例v11,能够看到,没使用cookie则反馈网页未登录
- 使用cookie登录
- 直接把cookie复制下来,而后手动放入请求头,案例v12
- http模块包含一些关于cookie的模块,经过他们咱们能够自动使用cookie
- CookieJar
- 管理存储cookie,向传出的http请求添加cookie
- cookie存储在内存中,CookieJar实例回收后cookie将消息
- FileCookieJar(filename, delayload=None, policy=None)
- 使用文件管理cookie
- filename是保存cookie的文件
- MozillaCookieJar(filename, delayload=None, policy=None)
- 建立与mozilla浏览器cookie.txt兼容的fileCookieJar实例
- LwpCookieJar(filename, delayload=None, policy=None)
- 建立与libwww-perl标准兼容的Set-Cookie3格式的FileCookieJar实例
- 他们之间的关系是CookieJar-->FileCookieJar-->MozillaCookie & LwpCookieJar
- 利用cookieJar访问妙味课堂,案例v13
- 自动使用cookie登录,大体流程是:
一、打开登录页面后自动经过用户名和密码登录
二、自动提取反馈回来的cookie
三、利用提取的cookie登录
- handler是Handler的实例,经常使用参看案例代码以下:
- 用来处理复杂请求
# 生成cookie管理器
cookie_handler = request.HTTPCookieProcessor(cookie)
# 生成http请求管理器
http_handler = request.HTTPHandler()
# 生成https管理器
https_handler = request.HTTPSHandler()
- 建立handler后,使用opener打开,打开后相应的业务由相应的handler处理
- cookie做为一个变量,打印出来,案例v14
- cookie的常见属性
- name:名称
- value:值
- domain:能够访问此cookie的域名
- path:能够访问的cookie页面路径
- expires:过时时间
- size:大小
- Http字段
- cookie的保存-FileCookieJar 案例v15
- cookie的读取,案例v16
''' 案例v5 利用parse模块模拟post请求 如下是分析百度词典的步骤: 一、打开F12 二、尝试输入girl单词,每次敲一个字母后都有请求 三、请求地址是https://fanyi.baidu.com/sug 四、利用Network-sug-Headers,查看发现Form Data的值是kw:girl 五、检查返回内容格式,根据返回头Response Headers下的Content-Type:application/json发现返回的是json格式内容,须要用到json包 ''' from urllib import request, parse import json ''' 大体流程是: 一、利用data构造内容,而后urlopen()打开 二、返回一个json格式结果 三、结果就应该是girl的释义 ''' baseurl = 'https://fanyi.baidu.com/sug' # 存放用来模拟form的数据必定是dict格式 data = { # girl是翻译输入的英文内容,应该由用户输入,此处使用硬编码 'kw':'girl' } # 须要使用parse模块对data编码获得str类型,可是要用bytes格式才能传递,因此用encode()编码 data = parse.urlencode(data).encode() print(type(data)) # 咱们须要构造一个请求头,请求头部应该至少包含传入的数据的长度 # request要求传入的请求头是一个dict格式 headers = { # 由于使用post,因此至少包含Content-Length字段 'Content-Length':len(data) } # 有了headers, data, url就能够尝试发出请求 rsp = request.urlopen(baseurl, data=data) # 读取返回内容,而后对内容进行解码,但下面解码失败了 json_data = rsp.read().decode('utf-8') print(type(json_data)) print(json_data) # 把json字符串转换成字典 json_data = json.loads(json_data) print(type(json_data)) print(json_data) for item in json_data['data']: print(item['k'],'---',item['v'])
''' 案例v6 利用parse模块模拟post请求 利用Request构造请求信息实例 如下是分析百度词典的步骤: 一、打开F12 二、尝试输入girl单词,每次敲一个字母后都有请求 三、请求地址是https://fanyi.baidu.com/sug 四、利用Network-sug-Headers,查看发现Form Data的值是kw:girl 五、检查返回内容格式,根据返回头Response Headers下的Content-Type:application/json发现返回的是json格式内容,须要用到json包 ''' from urllib import request, parse import json ''' 大体流程是: 一、利用data构造内容,而后urlopen()打开 二、返回一个json格式结果 三、结果就应该是girl的释义 ''' baseurl = 'https://fanyi.baidu.com/sug' # 存放用来模拟form的数据必定是dict格式 data = { # girl是翻译输入的英文内容,应该由用户输入,此处使用硬编码 'kw':'girl' } # 须要使用parse模块对data编码获得str类型,可是要用bytes格式才能传递,因此用encode()编码 data = parse.urlencode(data).encode() print(type(data)) # 咱们须要构造一个请求头,请求头部应该至少包含传入的数据的长度 # request要求传入的请求头是一个dict格式 headers = { # 由于使用post,因此至少包含Content-Length字段 'Content-Length':len(data) } # 构造一个Request实例,用来设置请求头各类信息 req = request.Request(baseurl, data, headers) # 由于已经构造了一个Request的请求实例,则能够直接传入urlopen中 rsp = request.urlopen(req) # 读取返回内容,而后对内容进行解码,但下面解码失败了 json_data = rsp.read().decode('utf-8') print(type(json_data)) print(json_data) # 把json字符串转换成字典 json_data = json.loads(json_data) print(type(json_data)) print(json_data) for item in json_data['data']: print(item['k'],'---',item['v'])
''' 案例v9 访问一个网址 更改本身的UserAgent进行假装 ''' from urllib import request, error if __name__ == '__main__': url='http://www.baidu.com' try: # 使用heads方法假装UA # 第一种方法 #headers = {} #headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36' #req = request.Request(url, headers=headers) # 第二种方法 req = request.Request(url) req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36') rsp = request.urlopen(req) html = rsp.read().decode() print(html) except error.HTTPError as e: print(e) except error.URLError as e: print(e) except Exception as e: print(e) print('Done...')
# 案例v13 from urllib import request,parse from http import cookiejar # 建立一个cookiejar的实例 cookie = cookiejar.CookieJar() # 生成cookie管理器 cookie_handler = request.HTTPCookieProcessor(cookie) # 生成http请求管理器 http_handler = request.HTTPHandler() # 生成https管理器 https_handler = request.HTTPSHandler() # 建立请求管理器 opener = request.build_opener(http_handler, https_handler, cookie_handler) def login(): ''' 负责初次登录 须要输入用户名密码,用来获取登录cookie凭证 :return: ''' # 点击登录按钮后,观察Network下发送的请求 url = 'http://study.miaov.com/account/login/ajaxindex' # 此值须要从页面中用户名和密码的元素中提取 data = { "account":"188xxxxxxxx", "pwd":"xxxxxxxxxx" } # 把数据进行编码 data = parse.urlencode(data).encode() # 建立一个请求对象 req = request.Request(url, data) # 使用opener发起请求 rsp = opener.open(req) def getHomePage(): url = "http://study.miaov.com/account/user/history" # 若是已经执行了login函数,则opener自动已经包含对应的cookie rsp = opener.open(url) html = rsp.read().decode() with open("rsp_v13.html", "w") as f: f.write(html) if __name__ == '__main__': login() getHomePage()
# 案例v14 # 在案例v13基础上打印cookie from urllib import request,parse from http import cookiejar # 建立一个cookiejar的实例 cookie = cookiejar.CookieJar() # 生成cookie管理器 cookie_handler = request.HTTPCookieProcessor(cookie) # 生成http请求管理器 http_handler = request.HTTPHandler() # 生成https管理器 https_handler = request.HTTPSHandler() # 建立请求管理器 opener = request.build_opener(http_handler, https_handler, cookie_handler) def login(): ''' 负责初次登录 须要输入用户名密码,用来获取登录cookie凭证 :return: ''' # 点击登录按钮后,观察Network下发送的请求 url = 'http://study.miaov.com/account/login/ajaxindex' # 此值须要从页面中用户名和密码的元素中提取 data = { "account":"188xxxxxxxx", "pwd":"xxxxxxxxxx" } # 把数据进行编码 data = parse.urlencode(data).encode() # 建立一个请求对象 req = request.Request(url, data) # 使用opener发起请求 rsp = opener.open(req) if __name__ == '__main__': ''' 执行完login以后,会获得受权孩子后的cookie 而后咱们尝试把cookie打印出来 ''' login() print(cookie) for item in cookie: print(type(item)) print(item)
# 案例v15 # 修改案例v13,改用文件管理cookie from urllib import request,parse from http import cookiejar filename = "cookie.txt" # 建立一个cookiejar的实例 cookie = cookiejar.MozillaCookieJar(filename) # 生成cookie管理器 cookie_handler = request.HTTPCookieProcessor(cookie) # 生成http请求管理器 http_handler = request.HTTPHandler() # 生成https管理器 https_handler = request.HTTPSHandler() # 建立请求管理器 opener = request.build_opener(http_handler, https_handler, cookie_handler) def login(): ''' 负责初次登录 须要输入用户名密码,用来获取登录cookie凭证 :return: ''' # 点击登录按钮后,观察Network下发送的请求 url = 'http://study.miaov.com/account/login/ajaxindex' # 此值须要从页面中用户名和密码的元素中提取 data = { "account":"188xxxxxxxx", "pwd":"xxxxxxxxxx" } # 把数据进行编码 data = parse.urlencode(data).encode() # 建立一个请求对象 req = request.Request(url, data) # 使用opener发起请求 rsp = opener.open(req) # 保存cookie到文件 # ignore_discard表示即便cookie将要被丢弃也要保存 # ignore_expires表示若是该文件中cookie即使已通过期,也要保存 cookie.save(ignore_discard=True, ignore_expires=True)
if __name__ == '__main__':
login()
# 案例v16 # 读取v15生成的cookie from urllib import request,parse from http import cookiejar # 建立一个cookiejar的实例 cookie = cookiejar.MozillaCookieJar() cookie.load("cookie.txt", ignore_discard=True, ignore_expires=True) # 生成cookie管理器 cookie_handler = request.HTTPCookieProcessor(cookie) # 生成http请求管理器 http_handler = request.HTTPHandler() # 生成https管理器 https_handler = request.HTTPSHandler() # 建立请求管理器 opener = request.build_opener(http_handler, https_handler, cookie_handler) def getHomePage(): url = "http://study.miaov.com/account/user/history" # 若是已经执行了login函数,则opener自动已经包含对应的cookie rsp = opener.open(url) html = rsp.read().decode() with open("rsp_v16.html", "w") as f: f.write(html) if __name__ == '__main__': getHomePage()