学习笔记-Python-爬虫1-urllib、chardet

# 爬虫
- 两大特征
- 按作者要求下载数据或者内容
- 能自动在网络上流窜
- 三大步骤
- 下载网页
- 提取正确的信息
- 根据一定规则自动跳转到另外的网页上执行
- 爬虫分类
- 通用爬虫
- 专用爬虫(聚焦爬虫)
- 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
- 代理用来隐藏真实访问地址,代理也不允许频繁访问某一个固定网站,所以,代理一定要很多很多
- 基本使用步骤:
1、设置代理地址
2、创建ProxyHandler
3、创建Opener
4、安装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登陆,大致流程是:
1、打开登陆页面后自动通过用户名和密码登陆
2、自动提取反馈回来的cookie
3、利用提取的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请求
以下是分析百度词典的步骤:
1、打开F12
2、尝试输入girl单词,每次敲一个字母后都有请求
3、请求地址是https://fanyi.baidu.com/sug
4、利用Network-sug-Headers,查看发现Form Data的值是kw:girl
5、检查返回内容格式,根据返回头Response Headers下的Content-Type:application/json发现返回的是json格式内容,需要用到json包
'''
from urllib import request, parse
import json

'''
大致流程是:
1、利用data构造内容,然后urlopen()打开
2、返回一个json格式结果
3、结果就应该是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构造请求信息实例
以下是分析百度词典的步骤:
1、打开F12
2、尝试输入girl单词,每次敲一个字母后都有请求
3、请求地址是https://fanyi.baidu.com/sug
4、利用Network-sug-Headers,查看发现Form Data的值是kw:girl
5、检查返回内容格式,根据返回头Response Headers下的Content-Type:application/json发现返回的是json格式内容,需要用到json包
'''
from urllib import request, parse
import json

'''
大致流程是:
1、利用data构造内容,然后urlopen()打开
2、返回一个json格式结果
3、结果就应该是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()

 

posted @ 2018-11-22 17:21  美滋滋的胖虎  阅读(238)  评论(0编辑  收藏  举报