1.爬虫基础

# 0 爬虫准备工作
- 参考资料
    - python网络数据采集, 图灵工业出版
    - 精通Python爬虫框架Scrapy, 人民邮电出版社
    - [Python3网络爬虫](http://blog.csdn.net/c406495762/article/details/72858983)
    - [Scrapy官方教程](http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html)
- 前提知识
    - url
    - http协议
    - web前端,html, css, js
    - ajax
    - re, xpath
    - xml
    
# 1. 爬虫简介
- 爬虫定义:网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),
是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。
另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
- 两大特征
    - 能按作者要求下载数据或者内容
    - 能自动在网络上流窜
- 三大步骤:
    - 下载网页
    - 提取正确的信息
    - 根据一定规则自动跳到另外的网页上执行上两步内容
    
- 爬虫分类
    - 通用爬虫
    - 专用爬虫(聚焦爬虫)

- Python网络包简介
    - Python2.x:urllib, urllib2, urllib3, httplib, httplib2, requests
    - Python3.x: urllib, urllib3, httplib2, requests
    - python2: urllib和urllib2配合使用,或者requests
    - Python3: urllib,requests
 
# 2. urllib
- 包含模块
    - urllib.request: 打开和读取urls
    - urllib.error: 包含urllib.request产生的常见的错误,使用try捕捉
    - urllib.parse:  包含解析url的方法
    - urllib.robotparse: 解析robots.txt文件
    - 案例v1
 
from urllib import request
'''
使用urllib.request请求一个网页内容,并把内容打印出来
'''


if __name__ == '__main__':

    url = "http://jobs.zhaopin.com/195435110251173.htm?ssidkey=y&ss=409&ff=03&sg=2644e782b8b143419956320b22910c91&so=1"
    # 打开相应url并把相应页面作为返回
    rsp = request.urlopen(url)

    # 把返回结果读取出来
    # 读取出来内容类型为bytes
    html = rsp.read()
    print(type(html))

    # 如果想把bytes内容转换成字符串,需要解码
    html = html.decode("utf-8")

    print(html)
   
- 网页编码问题解决
    - chardet 可以自动检测页面文件的编码格式,但是,可能有误
    - 需要安装, conda install chardet
    - 案例v2
'''
利用request下载页面
自动检测页面编码

'''

import urllib
import chardet

if __name__ == '__main__':
    url = 'http://stock.eastmoney.com/news/1407,20170807763593890.html'

    rsp = urllib.request.urlopen(url)

    html = rsp.read()

    #利用 chardet自动检测
    cs = chardet.detect(html)
    print(type(cs))
    print(cs)


    # 使用get取值保证不会出错
    html = html.decode(cs.get("encoding", "utf-8"))
    print(html)
- urlopen 的返回对象
    - 案例v3
import urllib

if __name__ == '__main__':
    url = 'http://stock.eastmoney.com/news/1407,20170807763593890.html'

    rsp = urllib.request.urlopen(url)

    print(type(rsp))
    print(rsp)


    print("URL: {0}".format( rsp.geturl()))
    print("Info: {0}".format(rsp.info()))
    print("Code: {0}".format(rsp.getcode()))

    html = rsp.read()


    # 使用get取值保证不会出错
    html = html.decode()
    - geturl: 返回请求对象的url
    - info: 请求反馈对象的meta信息
    - getcode:返回的http code    
- request.data 的使用
    - 访问网络的两种方法
        - get: 
            - 利用参数给服务器传递信息,
            - 参数为dict,然后用parse编码
            - 案例v4
from urllib import request, parse

'''
掌握对url进行参数编码的方法
需要使用parse模块
'''

if __name__ == '__main__':

    url = 'http://www.baidu.com/s?'
    wd = input("Input your keyword:")


    # 要想使用data, 需要使用字典结构
    qs = {
        "wd": wd
    }

    # 转换url编码
    qs = parse.urlencode(qs)
    print(qs)

    fullurl = url + qs
    print(fullurl)

    # 如果直接用可读的带参数的url,是不能访问的
    #fullurl = 'http://www.baidu.com/s?wd=大熊猫'

    rsp = request.urlopen(fullurl)

    html = rsp.read()


    # 使用get取值保证不会出错
    html = html.decode()

    print(html)
        - post
            - 一般向服务器传递参数使用
            - post是把信息自动加密处理
            - 我们如果想使用psot信息,需要用到data参数
            - 使用post,意味着Http的请求头可能需要更改:
                - Content-Type: application/x-www.form-urlencode
                - Content-Length: 数据长度
                - 简而言之,一旦更改请求方法,请注意其他请求头部信息相适应
            - urllib.parse.urlencode可以将字符串自动转换成上面的
            - 案例v5
'''
利用parse模块模拟post请求
分析百度词典
分析步骤:
1. 打开F12
2. 尝试输入单词girl,发现每敲一个字母后都有请求
3. 请求地址是 http://fanyi.baidu.com/sug
4. 利用NetWork-All-Hearders,查看,发现FormData的值是 kw:girl
5. 检查返回内容格式,发现返回的是json格式内容==>需要用到json包
'''

from urllib import request, parse
# 负责处理json格式的模块
import json

'''
大致流程是:
1. 利用data构造内容,然后urlopen打开
2. 返回一个json格式的结果
3. 结果就应该是girl的释义
'''

baseurl = 'http://fanyi.baidu.com/sug'


# 存放用来模拟form的数据一定是dict格式
data = {
    # girl是翻译输入的英文内容,应该是由用户输入,此处使用硬编码
    'kw': 'girl'
}

# 需要使用parse模块对data进行编码
data = parse.urlencode(data).encode("utf-8")

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'])
            - 为了更多的设置请求信息,单纯的通过urlopen函数已经不太好用了
            - 需要利用request.Request 类
            - 案例V6

'''
任务要求和内容跟V5 一样
本案例只是利用Request来实现v5的内容

利用parse模块模拟post请求
分析百度词典
分析步骤:
1. 打开F12
2. 尝试输入单词girl,发现每敲一个字母后都有请求
3. 请求地址是 http://fanyi.baidu.com/sug
4. 利用NetWork-All-Hearders,查看,发现FormData的值是 kw:girl
5. 检查返回内容格式,发现返回的是json格式内容==>需要用到json包
'''

from urllib import request, parse
# 负责处理json格式的模块
import json

'''
大致流程是:
1. 利用data构造内容,然后urlopen打开
2. 返回一个json格式的结果
3. 结果就应该是girl的释义
'''

baseurl = 'http://fanyi.baidu.com/sug'


# 存放用来模拟form的数据一定是dict格式
data = {
    # girl是翻译输入的英文内容,应该是由用户输入,此处使用硬编码
    'kw': 'girl'
}

# 需要使用parse模块对data进行编码
data = parse.urlencode(data).encode("utf-8")

#  我们需要构造一个请求头,请求头部应该至少包含传入的数据的长度
# request要求传入的请求头是一个dict格式

headers = {
    # 因为使用post,至少应该包含content-length 字段
    'Content-Length':len(data)
}

# 构造一个Request的实例
req = request.Request(url=baseurl, data=data, headers=headers)

# 因为已经构造了一个Request的请求实例,则所有的请求信息都可以封装在Request实例中
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'])
- urllib.error
    - URLError产生的原因:
        - 没网
        - 服务器链接失败
        - 知不道制定服务器
        - 是OSError的子类
        - 案例V7
'''\
URLError的使用
'''

from urllib import request, error


if __name__ == '__main__':

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

    try:

        req = request.Request(url)
        rsp = request.urlopen( req )
        html = rsp.read().decode()
        print(html)

    except error.URLError as e:
        print("URLError: {0}".format(e.reason))
        print("URLError: {0}".format(e))

    except Exception as e:
        print(e)
    - HTTPError, 是URLError的一个子类
        - 案例v8

'''\
URLError的使用
'''

from urllib import request, error


if __name__ == '__main__':

    url = "http:iiiiiiiiidu//www.baidu.com/welcome.html"

    url = "http://www.sipo.gov.cn/www"
    try:

        req = request.Request(url)
        rsp = request.urlopen( req )
        html = rsp.read().decode()
        print(html)

    except error.HTTPError as e:
        print("HTTPError: {0}".format(e.reason))
        print("HTTPError: {0}".format(e))

    except error.URLError as e:
        print("URLError: {0}".format(e.reason))
        print("URLError: {0}".format(e))

    except Exception as e:
        print(e)
    
    - 两者区别:
        - HTTPError是对应的HTTP请求的返回码错误, 如果返回错误码是400以上的,则引发HTTPError
        - URLError对应的一般是网络出现问题,包括url问题
        - 关系区别: OSError-URLError-HTTPError
- UserAgent 
    - UserAgent: 用户代理,简称UA, 属于heads的一部分,服务器通过UA来判断访问者身份
    - 常见的UA值,使用的时候可以直接复制粘贴,也可以用浏览器访问的时候抓包
        
            1.Android

            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
            Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
            Mozilla/5.0 (Linux; U; Android 2.2; en-gb; GT-P1000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1

            2.Firefox

            Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
            Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0

            3.Google Chrome

            Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36
            Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19

            4.iOS

            Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3
            Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A101a Safari/419.3

    - 设置UA可以通过两种方式:
        - heads
        - add_header
        - 案例v9 


'''
访问一个网址
更改自己的UserAgent进行伪装
'''
from urllib import request, error


if __name__ == '__main__':

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

    try:

        # 使用head方法伪装UA
        # headers = {}
        # headers['User-Agent'] = 'Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3'
        # req = request.Request( url, headers=headers)

        # 使用add_header方法
        req = request.Request(url)
        req.add_header("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 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>.............")

        
- ProxyHandler处理(代理服务器)
    - 使用代理IP,是爬虫的常用手段
    - 获取代理服务器的地址:
        - www.xicidaili.com
        - www.goubanjia.com
    - 代理用来隐藏真实访问中,代理也不允许频繁访问某一个固定网站,所以,代理一定要很多很多
    - 基本使用步骤:
        1. 设置代理地址
        2. 创建ProxyHandler
        3. 创建Opener
        4. 安装Opener
    - 案例v10
 
'''
使用代理访问百度网站


'''


from urllib import  request, error


if __name__ == '__main__':

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

    # 使用代理步骤
    # 1. 设置代理地址
    proxy = {'http': '120.194.18.90:81' }
    # 2. 创建ProxyHandler
    proxy_handler = request.ProxyHandler(proxy)
    # 3. 创建Opener
    opener = request.build_opener(proxy_handler)
    # 4. 安装Opener
    request.install_opener( opener)

    # 现在如果访问url,则使用代理服务器
    try:
        rsp = request.urlopen(url)
        html = rsp.read().decode()
        print(html)
    except error.URLError as e:
        print(e)
    except Exception as e:
        print(e)
   
- cookie & session
    - 由于http协议的无记忆性,人们为了弥补这个缺憾,所采用的一个补充协议
    - cookie是发放给用户(即http浏览器)的一段信息,session是保存在服务器上的对应的另一半信息,用来记录用户信息
    
- cookie和session的区别
    - 存放位置不同
    - cookie不安全
    - session会保存在服务器上一定时间,会过期
    - 单个cookie保存数据不超过4k, 很多浏览器限制一个站点最多保存20个
- session的存放位置
    - 存在服务器端
    - 一般情况,session是放在内存中或者数据库中
    - 没有cookie登录 案例v11,可以看到,没使用cookie则反馈网页为未登录状态

from urllib import request

if __name__ == '__main__':

    url = "http://www.renren.com/965187997/profile"

    rsp = request.urlopen(url)

    html = rsp.read().decode()

    with open("rsp.html", "w") as f:
        f.write(html)
    
- 使用cookie登录
    - 直接把cookie复制下来,然后手动放入请求头, 案例 v12
from urllib import request


if __name__ == '__main__':

    url = "http://www.renren.com/965187997/profile"

    headers = {
        "Cookie": "anonymid=jfosp2p2-48i1hh; depovince=BJ; _r01_=1; jebe_key=f2e12094-303b-4171-900f-ed304e5a5ba1%7C7629e5c8e0f7f334244eb5436ef05a2c%7C1523070488659%7C1%7C1523070515670; wp_fold=0; jebecookies=a201c15f-9745-40fc-9d32-7112f8cf849f|||||; ick_login=cbfe66e0-743c-46a4-a956-7d692056361d; _de=420A8DC764CD1624FC7C8526DA9A3A25; p=db36f5ff987e7e58c901f6194a22b7007; first_login_flag=1; ln_uact=13119144223; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; t=1b2976196819d4a57127f5b87ac495f77; societyguester=1b2976196819d4a57127f5b87ac495f77; id=965187997; xnsid=61e9001d; __utma=151146938.742687335.1523070758.1523070758.1523070758.1; __utmc=151146938; __utmz=151146938.1523070758.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmt=1; __utmb=151146938.1.10.1523070758; ver=7.0; loginfrom=null; JSESSIONID=abcIxsy_d_tR06bwXfEkw; _urm_965187997=21"
    }


    req = request.Request(url, headers=headers)

    rsp = request.urlopen(req)

    html = rsp.read().decode()


    with open("rsp.html", "w") as f:
        f.write(html)
    - 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):
            - 创建与mocilla浏览器cookie.txt兼容的FileCookieJar实例
        - LwpCookieJar(filename, delayload=None, policy=None):
            - 创建与libwww-perl标准兼容的Set-Cookie3格式的FileCookieJar实例
        - 他们的关系是: CookieJar-->FileCookieJar-->MozillaCookieJar & LwpCookieJar
    - 利用cookiejar访问人人, 案例13

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:
    '''

    # 此url需要从登录form的action属性中提取
    url = "http://www.renren.com/PLogin.do"

    # 此键值需要从登录form的两个对应input中提取name属性
    data = {
        "email": "13119144223",
        "password": "123456"
    }

    # 把数据进行编码
    data = parse.urlencode(data)

    # 创建一个请求对象
    req = request.Request(url, data=data.encode())

    # 使用opener发起请求
    rsp = opener.open(req)

def getHomePage():
    url = "http://www.renren.com/965187997/profile"

    # 如果已经执行了login函数,则opener自动已经包含相应的cookie值
    rsp = opener.open(url)


    html = rsp.read().decode()
    with open("rsp.html", "w") as f:
        f.write(html)

if __name__ == '__main__':
    login()
    getHomePage()
        - 自动使用cookie登录,大致流程是
        - 打开登录页面后自动通过用户名密码登录
        - 自动提取反馈回来的cookie
        - 利用提取的cookie登录隐私页面
    - handler是Handler的实例,常用参看案例代码
        - 用来处理复杂请求
        
                # 生成 cookie的管理器
                cookie_handler = request.HTTPCookieProcessor(cookie)
                # 创建http请求管理器
                http_handler = request.HTTPHandler()
                # 生成https管理器
                https_handler = request.HTTPSHandler()
             
    - 创立handler后,使用opener打开,打开后相应的业务由相应的hanlder处理
    - cookie作为一个变量,打印出来, 案例 v14

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:
    '''

    # 此url需要从登录form的action属性中提取
    url = "http://www.renren.com/PLogin.do"

    # 此键值需要从登录form的两个对应input中提取name属性
    data = {
        "email": "13119144223",
        "password": "123456"
    }

    # 把数据进行编码
    data = parse.urlencode(data)

    # 创建一个请求对象
    req = request.Request(url, data=data.encode())

    # 使用opener发起请求
    rsp = opener.open(req)

if __name__ == '__main__':
    '''
    执行完login之后,会得到授权之后的cookie
    我们尝试把cookie打印出来
    '''
    login()

    print(cookie)
    for item in cookie:
        print(type(item))
        print(item)
        for i in dir(item):
            print(i)
        - cookie的属性
            - name: 名称
            -  value: 值
            - domain:可以访问此cookie的域名
            - path: 可以发昂文此cookie的页面路径
            - expires:过期时间
            - size: 大小
            - Http字段
    - cookie的保存-FileCookieJar, 案例v15

from urllib import request, parse
from http import cookiejar

#  创建filecookiejar的实例
filename = "cookie.txt"
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:
    '''

    # 此url需要从登录form的action属性中提取
    url = "http://www.renren.com/PLogin.do"

    # 此键值需要从登录form的两个对应input中提取name属性
    data = {
        "email": "13119144223",
        "password": "123456"
    }

    # 把数据进行编码
    data = parse.urlencode(data)

    # 创建一个请求对象
    req = request.Request(url, data=data.encode())

    # 使用opener发起请求
    rsp = opener.open(req)

    # 保存cookie到文件
    # ignor_discard表示及时cookie将要被丢弃也要保存下来
    # ignore_expire表示如果该文件中cookie即使已经过期,保存
    cookie.save(ignore_discard=True, ignore_expires=True)


if __name__ == '__main__':
    login()
    - cookie的读取, 案例v16

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://www.renren.com/965187997/profile"

    # 如果已经执行了login函数,则opener自动已经包含相应的cookie值
    rsp = opener.open(url)


    html = rsp.read().decode()
    with open("rsp.html", "w") as f:
        f.write(html)

if __name__ == '__main__':
    getHomePage()
    
- SSL
    - SSL证书就是指遵守SSL安全套阶层协议的服务器数字证书(SercureSocketLayer)
    - 美国网景公司开发
    - CA(CertifacateAuthority)是数字证书认证中心,是发放,管理,废除数字证书的收信人的第三方机构
    - 遇到不信任的SSL证书,需要单独处理,案例v17
    

from urllib import request

# 导入pythopn ssl处理模块
import ssl

# 利用非认证上下文环境替换认证的向下文环境
ssl._create_default_https_context = ssl._create_unverified_context

url = "https://www.12306.cn/mormhweb/"
rsp = request.urlopen(url)

html = rsp.read().decode()

print(html)
- js加密
    - 有的反爬虫策略采用js对需要传输的数据进行加密处理(通常是取md5值)
    - 经过加密,传输的就是密文,但是
    - 加密函数或者过程一定是在浏览器完成,也就是一定会把代码(js代码)暴露给使用者
    - 通过阅读加密算法,就可以模拟出加密过程,从而达到破解
    - 过程参看案例v18, 

'''
破解有道词典
V1
'''

from urllib import request, parse


def youdao(key):

    url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

    data = {
        "i": "boy",
        "from":"AUTO",
        "to": "AUTO",
        "smartresult": "dict",
        "client": "fanyideskweb",
        "salt": "1523100789519",
        "sign": "b8a55a436686cd89873fa46514ccedbe",
        "doctype": "json",
        "version": "2.1",
        "keyfrom": "fanyi.web",
        "action":"FY_BY_REALTIME",
        "typoResult": "false"
    }

    # 参数data需要是bytes格式
    data = parse.urlencode(data).encode()

    headers = {
                  "Accept": "application/json,text/javascript,*/*;q=0.01",
                  #"Accept-Encoding": "gzip,deflate",
                  "Accept-Language": "zh-CN,zh;q=0.9",
                  "Connection": "keep-alive",
                  "Content-Length": "200",
                  "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
                  "Cookie": "OUTFOX_SEARCH_USER_ID=-1548144101@10.168.8.76;JSESSIONID=aaaTLWzfvp5Hfg9mAhFkw;OUTFOX_SEARCH_USER_ID_NCOO=1999296830.4784973;___rl__test__cookies=1523100789517",
                  "Host": "fanyi.youdao.com",
                  "Origin": "http://fanyi.youdao.com",
                  "Referer": "http://fanyi.youdao.com/",
                  "User-Agent": "Mozilla/5.0( X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36 X-Requested-With: XMLHttpRequest"
    }

    req = request.Request(url=url, data=data, headers=headers)

    rsp = request.urlopen(req)

    html = rsp.read().decode()
    print(html)

if __name__ == '__main__':
    youdao("boy")
v19
    - 过程比较啰嗦,笔记比较少,仔细观察

'''
V2
处理js加密代码
'''

'''
通过查找,能找到js代码中操作代码

1. 这个是计算salt的公式 r = "" + ((new Date).getTime() + parseInt(10 * Math.random(), 10));
2. sign: n.md5("fanyideskweb" + t + r + "ebSeFb%=XZ%T[KZ)c(sy!");
md5一共需要四个参数,第一个和第四个都是固定值的字符串,第三个是所谓的salt,第二个是。。。。。
第二个参数就是输入的要查找的单词

'''


def getSalt():
    '''
    salt公式是:  "" + ((new Date).getTime() + parseInt(10 * Math.random(), 10));
    把他翻译成python代码
    :return:
    '''
    import time, random

    salt = int(time.time()*1000) + random.randint(0,10)

    return salt

def getMD5(v):
    import hashlib
    md5 = hashlib.md5()

    # update需要一共bytes格式的参数
    md5.update(v.encode("utf-8"))

    sign = md5.hexdigest()

    return sign


def getSign(key, salt):

    sign = 'fanyideskweb'+ key + str(salt) + "ebSeFb%=XZ%T[KZ)c(sy!"
    sign = getMD5(sign)

    return sign

from urllib import request, parse


def youdao(key):

    url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

    salt = getSalt()

    data = {
        "i": key,
        "from":"AUTO",
        "to": "AUTO",
        "smartresult": "dict",
        "client": "fanyideskweb",
        "salt": str(salt) ,
        "sign": getSign(key, salt),
        "doctype": "json",
        "version": "2.1",
        "keyfrom": "fanyi.web",
        "action":"FY_BY_REALTIME",
        "typoResult": "false"
    }

    print(data)

    # 参数data需要是bytes格式
    data = parse.urlencode(data).encode()

    headers = {
        "Accept": "application/json,text/javascript,*/*;q=0.01",
        #"Accept-Encoding": "gzip,deflate",
        "Accept-Language": "zh-CN,zh;q=0.9",
        "Connection": "keep-alive",
        "Content-Length": len(data),
        "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
        "Cookie": "OUTFOX_SEARCH_USER_ID=-1548144101@10.168.8.76;JSESSIONID=aaaTLWzfvp5Hfg9mAhFkw;OUTFOX_SEARCH_USER_ID_NCOO=1999296830.4784973;___rl__test__cookies=1523100789517",
        "Host": "fanyi.youdao.com",
        "Origin": "http://fanyi.youdao.com",
        "Referer": "http://fanyi.youdao.com/",
        "User-Agent": "Mozilla/5.0( X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36 X-Requested-With: XMLHttpRequest"
    }

    req = request.Request(url=url, data=data, headers=headers)

    rsp = request.urlopen(req)

    html = rsp.read().decode()
    print(html)

if __name__ == '__main__':
    youdao("boy")
    
- ajax
    - 异步请求
    - 一定会有url,请求方法,可能有数据
    - 一般使用json格式
    - 案例,爬去豆瓣电影, 案例v20
 
'''
爬去豆瓣电影数据
了解ajax的基本爬去方式

'''
from urllib import request
import json


url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=40&limit=20"


rsp = request.urlopen(url)
data = rsp.read().decode()

data = json.loads(data)

print(data)

   
# Requests-献给人类
- HTTP for Humans,更简洁更友好
- 继承了urllib的所有特征
- 底层使用的是urllib3
- 开源地址: https://github.com/requests/requests
- 中文文档: http://docs.python-requests.org/zh_CN/latest/index.html   
- 安装: conda install requests
- get请求
    - requests.get(url)
    - requests.request("get", url)
    - 可以带有headers和parmas参数
    - 案例v21
import requests


url = "http://www.baidu.com"
# 两种请求方式
# 使用get请求
rsp = requests.get(url)
print(rsp.text)

# 使用request请求
rsp = requests.request("get", url)
print(rsp.text)
- get返回内容
    - 案例v22
 
'''
使用参数headers和params
研究返回结果

'''

import requests

# 完整访问url是下面url加上参数构成
url = "http://www.baidu.com/s?"

kw = {
    "wd": "王八蛋"
}


headers = {
    "User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36"
}
rsp = requests.get(url, params=kw, headers=headers )

print(rsp.text)
print(rsp.content)
print(rsp.url)
print(rsp.encoding)
print(rsp.status_code) # 请求返回码
   
- post
    - rsp = requests.post(url, data=data)
    - 参看案例23
'''
python中正则模块是re
使用大致步骤:
1. compile函数讲正则表达式的字符串便以为一个Pattern对象
2. 通过Pattern对象的一些列方法对文本进行匹配,匹配结果是一个Match对象
3. 用Match对象的方法,对结果进行操纵

'''


import re

# \d表示以数字
# 后面+号表示这个数字可以出现一次或者多次
s = r"\d+" # r表示后面是原生字符串,后面不需要转义


# 返回Pattern对象
pattern = re.compile(s)

# 返回一个Match对象
# 默认找到一个匹配就返回
m = pattern.match("one12two2three3")

print(type(m))
# 默认匹配从头部开始,所以此次结果为None
print(m)

# 返回一个Match对象
# 后面为位置参数含义是从哪个位置开始查找,找到哪个位置结束
m = pattern.match("one12two2three3", 3, 10)

print(type(m))
# 默认匹配从头部开始,所以此次结果为None
print(m)


print(m.group())

print(m.start(0))
print(m.end(0))
print(m.span(0))
    - date, headers要求dict类型
- proxy
   - 
        
            proxies = {
            "http":"address of proxy",
            "https": "address of proxy"
            }
            
            rsp = requests.request("get", "http:xxxxxx", proxies=proxies)
   - 代理有可能报错,如果使用人数多,考虑安全问题,可能会被强行关闭
   
- 用户验证
    - 代理验证
    
            #可能需要使用HTTP basic Auth, 可以这样
            # 格式为  用户名:密码@代理地址:端口地址
            proxy = { "http": "china:123456@192.168.1.123:4444"}
            rsp = requests.get("http://baidu.com", proxies=proxy)
- web客户端验证
    - 如果遇到web客户端验证,需要添加auth=(用户名,密码)
    
            autu=("test1", "123456")#授权信息
            rsp = requests.get("http://www.baidu.com", auth=auth)
- cookie
    - requests可以自动处理cookie信息
    
        
              rsp = requests.get("http://xxxxxxxxxxx")
              # 如果对方服务器给传送过来cookie信息,则可以通过反馈的cookie属性得到
              # 返回一个cookiejar实例
              cookiejar = rsp.cookies   
              
              
              #可以讲cookiejar转换成字典
              cookiedict = requests.utils.dict_from_cookiejar(cookiejar)         
    
- session
    - 跟服务器端session不是一个东东
    - 模拟一次会话,从客户端浏览器链接服务器开始,到客户端浏览器断开
    - 能让我们跨请求时保持某些参数,比如在同一个session实例发出的 所有请求之间保持cookie
    
    
            # 创建session对象,可以保持cookie值
            ss = requests.session()
            
            headers = {"User-Agetn":"xxxxxxxxxxxxxxxxxx"}
            
            data = {"name":"xxxxxxxxxxx"}
            
            # 此时,由创建的session管理请求,负责发出请求,
            ss.post("http://www.baidu.com", data=data, headers=headers)
            
            rsp = ss.get("xxxxxxxxxxxx")
            
- https请求验证ssl证书
    - 参数verify负责表示是否需要验证ssL证书,默认是True
    - 如果不需要验证ssl证书,则设置成False表示关闭
    
        
            rsp = requests.get("https://www.baidu.com", verify=False)
            # 如果用verify=True访问12306,会报错,因为他证书有问题 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值