python爬虫02 - 爬虫请求模块 request库 json数据

1. urllib.request模块

先用之前学到过的方法解决

第一种方法

先创建一个爬取图片.py 在新标签页中打开图片
python爬虫02 - 爬虫请求模块 request库 json数据_第1张图片
这就是该图片的url
在这里插入图片描述

import requests

#图片的url
url='https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596188551&di=3c06d3cd21c706c6c9c562f2bf76f56e&src=http://a3.att.hudong.com/14/75/01300000164186121366756803686.jpg'

req=requests.get(url)

fn=open('code.png','wb')
fn.write(req.content)

fn.close()  

执行后
python爬虫02 - 爬虫请求模块 request库 json数据_第2张图片

第二种方法

import requests

url='https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596188551&di=3c06d3cd21c706c6c9c562f2bf76f56e&src=http://a3.att.hudong.com/14/75/01300000164186121366756803686.jpg'

req=requests.get(url)
#
# fn=open('code.png','wb')
# fn.write(req.content)
#
# fn.close()

with open('code2.png','wb') as f:
    f.write(req.content)

python爬虫02 - 爬虫请求模块 request库 json数据_第3张图片

第三种方法

import requests

from urllib import request

url='https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596188551&di=3c06d3cd21c706c6c9c562f2bf76f56e&src=http://a3.att.hudong.com/14/75/01300000164186121366756803686.jpg'

request.urlretrieve(url,'code3.png')
# req=requests.get(url)
#
# fn=open('code.png','wb')
# fn.write(req.content) #content只是二进制数据
#
# fn.close()
#
# with open('code2.png','wb') as f:
#     f.write(req.content)

运行一下
python爬虫02 - 爬虫请求模块 request库 json数据_第4张图片
在这里插入图片描述

python爬虫02 - 爬虫请求模块 request库 json数据_第5张图片

1.1 版本

python2 :urllib2、urllib
python3 :把urllib和urllib2合并,urllib.request

1.2 常用的方法

• urllib.request.urlopen(“网址”) 作用 :向网站发起一个请求并获取响应 (或者是直接获取响应)
• 字节流 = response.read()
• 字符串 = response.read().decode(“utf-8”)
• urllib.request.Request"网址",headers=“字典”) urlopen()不支持重构User-Agent

实际操作

新建一个python文件

import urllib.request


# 向百度发起一个请求  得到一个响应结果 用一个变量接收

response=urllib.request.urlopen('https://www.baidu.com/')

print(response)


<http.client.HTTPResponse object at 0x0000000002504E20>
是一个对象
import urllib.request


# 向百度发起一个请求  得到一个响应结果 用一个变量接收

response=urllib.request.urlopen('https://www.baidu.com/')

#从响应对象中获取数据  read()函数来读取数据
print(response.read())

b'\r\n\r\n\t\r\n\r\n\r\n\t\r\n\r\n'
咱们拿到的这个response数据应该是网页源码  但是这些太少了

咱们拿到的网页源码应该是这些
python爬虫02 - 爬虫请求模块 request库 json数据_第6张图片
上面操作拿到的显然太少了 原因是百度在这里做了反爬了
咱们换个网站 一会再解决这个问题
在这里插入图片描述
python爬虫02 - 爬虫请求模块 request库 json数据_第7张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第8张图片
但是没有文字python爬虫02 - 爬虫请求模块 request库 json数据_第9张图片
因为python爬虫02 - 爬虫请求模块 request库 json数据_第10张图片
这个b bit数据类型 字节
可以查看它的类型

import urllib.request


# 向百度发起一个请求  得到一个响应结果 用一个变量接收

response=urllib.request.urlopen('https://qq.yh31.com/')

#从响应对象中获取数据  read()函数来读取数据
# print(response.read())
html=response.read()
print(type(html))

<class 'bytes'>    类型是字节

但是现在我想看到的是字符串类型
字节转换成字符串 用解码 decode

import urllib.request


# 向百度发起一个请求  得到一个响应结果 用一个变量接收

response=urllib.request.urlopen('https://qq.yh31.com/')

#从响应对象中获取数据  read()函数来读取数据
# print(response.read())
html=response.read().decode('utf-8')

print(html)		

python爬虫02 - 爬虫请求模块 request库 json数据_第11张图片

这会就正常了 因为源码实在太多了

咱们再来搞一搞刚才百度的反爬 可能是我们没有添加headers 请求头

import urllib.request


# 向百度发起一个请求  得到一个响应结果 用一个变量接收
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}

response=urllib.request.urlopen('https://www.baidu.com/',headers=headers)

#从响应对象中获取数据  read()函数来读取数据
# print(response.read())
html=response.read().decode('utf-8')

print(html)


TypeError: urlopen() got an unexpected keyword argument 'headers'
类型错误:urlopen()获得意外的关键字参数“headers”

因为urlopen()这个方法是不支持重构headers的

最终版本

• urllib.request.Request"网址",headers=“字典”)

import urllib.request


# 请求百度的数据(网页源码)
url='https://www.baidu.com/'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
#1.创建请求对象(构建User-Agent)
response=urllib.request.Request(url,headers=headers)

#2.获取响应对象(urlopen())
res=urllib.request.urlopen(response)

#3.读取响应对象的内容(read().decode('utf-8'))

html=res.read().decode('utf-8')
print(html)

python爬虫02 - 爬虫请求模块 request库 json数据_第12张图片
这就和用谷歌浏览器打开的百度源码页内容一样了
python爬虫02 - 爬虫请求模块 request库 json数据_第13张图片

1.3 响应对象

• read() 读取服务器响应的内容 (读取到的是一个字节流数据 所以后面要加上.decode())
• getcode() 返回HTTP的响应码
• geturl() 返回实际数据的URL(防止重定向问题)

import urllib.request


# 请求百度的数据(网页源码)
url='https://www.baidu.com/'

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
#1.创建请求对象(构建User-Agent)
response=urllib.request.Request(url,headers=headers)


#2.获取响应对象(urlopen())
res=urllib.request.urlopen(response)

#3.读取响应对象的内容(read().decode('utf-8'))

html=res.read().decode('utf-8')
# print(html)
print(res.getcode())#返回状态码

print(res.geturl())# 返回实际的请求网站


200
https://www.baidu.com/

urllib 是python自带的请求模块 request是第三方的请求模块

2. urllib.parse模块

2.1 常用方法

• urlencode(字典) 参数就是字典
• quote(字符串) (这个里面的参数是个字符串)

实际操作0

我们先用百度搜素海贼王
python爬虫02 - 爬虫请求模块 request库 json数据_第14张图片
因为是get请求 请求参数会显示在url上
在这里插入图片描述
后面的参数我们先不看 我们先拿关键的部分
在这里插入图片描述

url='https://www.baidu.com/s?wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B'

我们发现海贼王没了 %E6%B5%B7%E8%B4%BC%E7%8E%8B
原因就是 我们在向一个网页发起请求的时候 比如在百度的搜素框里搜索一个中文 海贼王
也就是它要把中文向服务器提交 但是网站只能识别 ascii 码 也就是英文 它真正提交传输内容的时候是ascii码 是网站给你做了这么一个编码 网页是不识别中文的
所以海贼王变成了十六进制的这么个东西%E6%B5%B7%E8%B4%BC%E7%8E%8B
比如你搜索关键字 比如是用拼串 如果直接加上你要搜索的关键字 (比如美女) 那么你的程序就有可能会出现问题 所以我们要将汉字进行手动的编码
如何进行手动编码呢 就要用到urllib.parse模块的 urlencode( ) 的这个方法

我们先可以试试这个%E6%B5%B7%E8%B4%BC%E7%8E%8B 是不是就是海贼王
三个百分号为一个汉字
那么%E6%B5%B7 就是海 %E8%B4%BC就是贼 %E7%8E%8B就是王
可以使用工具urldecode解码

https://tool.chinaz.com/tools/urlencode.aspx
python爬虫02 - 爬虫请求模块 request库 json数据_第15张图片


import urllib.parse

# url='https://www.baidu.com/s?wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B'


r={'wd':'海贼王'}  #这个是字典  传集合 也就是没有键 是会报错的


result=urllib.parse.urlencode(r)

print(result)



wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B

练习一

# 导入模块
import urllib.parse

import urllib.request


#在百度上输入一个内容 例如:美女 数据保存到本地文件  美女.html

#baseurl  初始url
baseurl='https://www.baidu.com/s?'#此处的s?比较重要 不能丢

content=input('你要搜索的内容:')

wd={'wd':content}  #当然也可以是d={'wd':content} 前面的那个变量可以随便编  但是key值就是wb 这个不能错

content=urllib.parse.urlencode(wd)

#拼接url
url=baseurl+content

print(url)

你要搜索的内容:美女 #回车   此处可以自行输入内容 
https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3

练习之最终版本

# 导入模块
import urllib.parse

import urllib.request


#在百度上输入一个内容 例如:美女 数据保存到本地文件  美女.html

#baseurl  初始url
baseurl='https://www.baidu.com/s?'#此处的s?比较重要 不能丢

content=input('你要搜索的内容:')

wd={'wd':content}  #当然也可以是d={'wd':content} 前面的那个变量可以随便编  但是key值就是wb 这个不能错

content=urllib.parse.urlencode(wd)

#拼接url
url=baseurl+content

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

#创建请求对象
req=urllib.request.Request(url,headers=headers)

#获取响应对象
res=urllib.request.urlopen(req)
#读取
html=res.read().decode('utf-8')

#保存文件
with open('美女.html','w',encoding='utf-8')as f:
    f.write(html)

python爬虫02 - 爬虫请求模块 request库 json数据_第16张图片

小结

反爬 ua refer cookie 可以把这些添加进去来反制一些反爬python爬虫02 - 爬虫请求模块 request库 json数据_第17张图片

2.2补充 urllib.parse模块中的两个常用方法

• urlencode(字典) 参数就是字典
• quote(字符串) 这个里面的参数是个字符串

urlencode(字典)

import urllib.parse

baseurl='https://www.baidu.com/s?'


r={'wd':'海贼王'}

result=urllib.parse.urlencode(r)

url=baseurl+result
print(url)


https://www.baidu.com/s?wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B

quote(字符串)

quote(引用)

import urllib.parse

key=input('输入内容:')

baseurl='https://www.baidu.com/s?wd='

r=urllib.parse.quote(key)

url=baseurl+r

print(url)


输入内容:姑娘
https://www.baidu.com/s?wd=%E5%A7%91%E5%A8%98

二者区别应该也就是baseurl中的wd=

练习一爬取百度贴吧

python爬虫02 - 爬虫请求模块 request库 json数据_第18张图片
需求:
1输入要爬取贴吧的主题
2输入爬取的起始页和终止页
3把每一页的内容保存到本地

我们可以去网上搜索一些请求头

需求: 1输入要爬取贴吧的主题 2输入爬取的起始页和终止页 3把每一页的内容保存到本地

分析
https://tieba.baidu.com/f?kw=%E4%B8%AD%E5%9B%BD&ie=utf-8&pn=0 第一页
https://tieba.baidu.com/f?kw=%E4%B8%AD%E5%9B%BD&ie=utf-8&pn=50 第二页https://tieba.baidu.com/f?kw=%E4%B8%AD%E5%9B%BD&ie=utf-8&pn=100 第三页
pn=(当前页数-1)*50kw 贴吧的主题

import random
import urllib.request
import urllib.parse
#随机获取一个user-agent


headers_list = [{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'}]

headers=random.choice(headers_list)

name=input('请输入贴吧名:')

start=int(input('请输入起始页:'))
end=int(input('请输入结束页:'))

#对贴吧名name做个编码
kw={'kw':'%s'%name}

kw=urllib.parse.urlencode(kw)

#开始拼接url 发起请求 获取响应
for i in range(start,end+1):
    #开始拼接url

    pn=(i-1)*50
    baseurl='https://tieba.baidu.com/f?'

    url=baseurl+kw+'&pn='+str(pn)# 因为这是一个字符串的拼串
    #创建请求对象
    req=urllib.request.Request(url,headers=headers)
    #获取响应对象
    res=urllib.request.urlopen(req)
    #读取
    html=res.read().decode('utf-8')
    #写入文件
    filename='第'+str(i)+'页%s贴吧.html'%name
    with open(filename,'w',encoding='utf-8') as f:
        print('正在爬取%d页'%i)
        f.write(html)

练习二爬取百度贴吧(引入函数)

import urllib.request
import urllib.parse

#读取页面
def readPage(url):
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}
    req = urllib.request.Request(url, headers=headers)

    res = urllib.request.urlopen(req)

    html = res.read().decode('utf-8')
    return html

#写入文件
def writePage(filename,html):

    with open(filename, 'w', encoding='utf-8') as f:
        f.write(html)
        print('写入成功')


#主函数
def main():
    name = input('请输入贴吧名:')

    start = int(input('请输入起始页:'))
    end = int(input('请输入结束页:'))
    # 对贴吧名name做个编码
    kw = {'kw': '%s' % name}
    #kw = {'kw':name} 这样更简单 

    kw = urllib.parse.urlencode(kw)
    # 开始拼接url 发起请求 获取响应
    for i in range(start, end + 1):
        # 开始拼接url

        pn = (i - 1) * 50
        baseurl = 'https://tieba.baidu.com/f?'

        url = baseurl + kw + '&pn=' + str(pn)  # 因为这是一个字符串的拼串
        filename = '第' + str(i) + '页%s贴吧.html' % name
        html=readPage(url)
        writePage(filename,html)
if __name__ == '__main__':
    main()

练习三爬取百度贴吧(引入类)

import urllib.request
import urllib.parse



class BaiduSpider:
    def __init__(self):
        #把常用的不变 的放到这里
        self.headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}
        self.baseurl = 'https://tieba.baidu.com/f?'

    def readPage(self,url):
        req = urllib.request.Request(url, headers=headers)

        res = urllib.request.urlopen(req)

        html = res.read().decode('utf-8')
        return html
    def writePage(self,filename,html):
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(html)
            print('写入成功')

    def main(self):
        name = input('请输入贴吧名:')

        start = int(input('请输入起始页:'))
        end = int(input('请输入结束页:'))
        # 对贴吧名name做个编码
        kw = {'kw':name}

        kw = urllib.parse.urlencode(kw)
        # 开始拼接url 发起请求 获取响应
        for i in range(start, end + 1):
            # 开始拼接url

            pn = (i - 1) * 50
            # baseurl = 'https://tieba.baidu.com/f?'这个就不用了

            url = self.baseurl + kw + '&pn=' + str(pn)  # 因为这是一个字符串的拼串
            filename = '第' + str(i) + '页%s贴吧.html' % name
            html = self.readPage(url)
            self.writePage(filename, html)

if __name__ == '__main__':
    #创建类的实例
    spider=BaiduSpider()
    spider.main()



请输入贴吧名:土狗
请输入起始页:1
请输入结束页:3
写入成功
写入成功
写入成功

3. 请求方式

• GET 特点 :查询参数在URL地址中显示
• POST
• 在Request方法中添加data参数 urllib.request.Request(url,data=data,headers=headers)
• data :表单数据以bytes类型提交,不能是str

案例思路

python爬虫02 - 爬虫请求模块 request库 json数据_第19张图片
在这里插入图片描述
就是比如图中的你好 这些数据 以post请求提交给服务器 提交到了form表单.

python爬虫02 - 爬虫请求模块 request库 json数据_第20张图片
提交是手动提交的 我们可以做一个有道翻译小软件.
首先这个请求的url地址是可以帮我们做这个翻译的
就是在这里插入图片描述
中的在这里插入图片描述
http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
然后我们的输入内容会在form表单里面 这个表单里有些数据是变的 有些数据是不变的python爬虫02 - 爬虫请求模块 request库 json数据_第21张图片
你会发现这里面特别像字典 key-value
我们先把他们全部拿下来 复制 那么我们就可以把form表单里 的数据变成一个字典
然后再把这个字典类的数据以post的方式提交到上面说的url地址上
但是提交的时候我们用的是urllib 用其中的方法request.Request( ) 但是用它的额话 提交的数据得是一个字节 那么我们就得把字典数据类型转化成字节流

import urllib.parse
import urllib.request
#请输入要翻译的内容

key=input('请输入要翻译的内容:')

#把提交的form表单数据转换为byte类型数据
data={
    'i': key,
    'from': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15880623642174',
    'sign': 'c6c2e897040e6cbde00cd04589e71d4e',
    'ts': '1588062364217',
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom':'fanyi.web',
    'action': 'FY_BY_CLICKBUTTION'
}

data=urllib.parse.urlencode(data) #就是把字典这个数据做一个编码
#把date数据转换成字节流数据
data=bytes(data,'utf-8')

#发起请求 获取响应
url='http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}

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

res=urllib.request.urlopen(req)

html=res.read().decode('utf-8')
print(html)


请输入要翻译的内容:好你妹
{"errorCode":50}
错误码 50   我们看看哪里错了

可能是他们的前端比较强 做过了处理
url=‘http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule’
我们把_o去掉
url中去掉 _o

import urllib.parse
import urllib.request
#请输入要翻译的内容

key=input('请输入要翻译的内容:')

#把提交的form表单数据转换为byte类型数据
data={
    'i': key,
    'from': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15880623642174',
    'sign': 'c6c2e897040e6cbde00cd04589e71d4e',
    'ts': '1588062364217',
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom':'fanyi.web',
    'action': 'FY_BY_CLICKBUTTION'
}

data=urllib.parse.urlencode(data) #就是把字典这个数据做一个编码
#把date数据转换成字节流数据
data=bytes(data,'utf-8')

#发起请求 获取响应
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}

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

res=urllib.request.urlopen(req)

html=res.read().decode('utf-8')
print(html,type(html))



请输入要翻译的内容:咦嘿嘿


{"type":"ZH_CN2EN","errorCode":0,"elapsedTime":5,"translateResult":[[{"src":"咦嘿嘿","tgt":"Hey hey hey"}]]}
 <class 'str'>

翻译成了Hey hey hey …
而且看出了这个html类型是个str
原因就是
python爬虫02 - 爬虫请求模块 request库 json数据_第22张图片
而控制台打印的结果 它会把引号省去
python爬虫02 - 爬虫请求模块 request库 json数据_第23张图片
所以这个html 数据 是个字符串 json类型的字符串 它很像一个字典
我们需要导入一个json
在这里插入图片描述

import urllib.parse
import urllib.request
import json
#请输入要翻译的内容

key=input('请输入要翻译的内容:')

#把提交的form表单数据转换为byte类型数据
data={
    'i': key,
    'from': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15880623642174',
    'sign': 'c6c2e897040e6cbde00cd04589e71d4e',
    'ts': '1588062364217',
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom':'fanyi.web',
    'action': 'FY_BY_CLICKBUTTION'
}

data=urllib.parse.urlencode(data) #就是把字典这个数据做一个编码
#把date数据转换成字节流数据
data=bytes(data,'utf-8')

#发起请求 获取响应
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}

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

res=urllib.request.urlopen(req)

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

#把json类型的字符串转换成字典
r_dict=json.loads(html) #这个操作后 这个jason类型的字符串就变成了了字典
print(r_dict,type(r_dict))



请输入要翻译的内容:f     
{'type': 'EN2ZH_CN', 'errorCode': 0, 'elapsedTime': 0, 'translateResult': [[{'src': 'f', 'tgt': 'f'}]]} <class 'dict'>

而我们想要的是字典中键(key)tgt对应的值(value)
且从中我们可以看出 ‘translateResult’: [[{‘src’: ‘f’, ‘tgt’: ‘f’}]]
在这里插入图片描述
但是呢r是一个列表 我们的目标是取到此列表中的列表中的字典的值
所以
python爬虫02 - 爬虫请求模块 request库 json数据_第24张图片
于是乎 可以有了更简单直接的方法
python爬虫02 - 爬虫请求模块 request库 json数据_第25张图片

有道字典小程序

import urllib.parse
import urllib.request
import json
#请输入要翻译的内容

key=input('请输入要翻译的内容:')

#把提交的form表单数据转换为byte类型数据
data={
    'i': key,
    'from': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15880623642174',
    'sign': 'c6c2e897040e6cbde00cd04589e71d4e',
    'ts': '1588062364217',
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom':'fanyi.web',
    'action': 'FY_BY_CLICKBUTTION'
}

data=urllib.parse.urlencode(data) #就是把字典这个数据做一个编码
#把date数据转换成字节流数据
data=bytes(data,'utf-8')

#发起请求 获取响应
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}

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

res=urllib.request.urlopen(req)

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

#把json类型的字符串转换成字典
r_dict=json.loads(html)

r=r_dict['translateResult']
content=r[0][0]['tgt']
print(content)

4. requests模块

4.1 安装

• pip install requests
• 在开发工具中安装

安装可以直接到我们的设置里面
python爬虫02 - 爬虫请求模块 request库 json数据_第26张图片
这这里点右上角的加号
在这里插入图片描述
左下角的intsall package 安装
如果还是不行的话 我们可以换源安装
python爬虫02 - 爬虫请求模块 request库 json数据_第27张图片

4.2 request常用方法

• requests.get(网址)

4.3 响应对象response的方法

• response.text 返回unicode格式的数据(str)
• response.content 返回字节流数据(二进制)
• response.content.decode(‘utf-8’) 手动进行解码
• response.url 返回url
• response.encode() = ‘编码’
response.encode(‘utf-8’)
response.encoding=‘utf-8’

4.4 requests模块发送 POST请求

Get是用来从服务器上获得数据,而Post是用来向服务器上传递数据。
在这里插入图片描述
在这里插入图片描述
后面的操作会用到后面用到时传入的data是一个字典

4.5 requests设置代理

• 使用requests添加代理只需要在请求方法中(get/post)传递proxies参数就可以了
• 代理网站
快代理:http://www.kuaidaili.com/
代理云:http://www.dailiyun.com/

request设置代理

测试请求头网址: http://httpbin.org/user-agent

在这里插入图片描述
python爬虫02 - 爬虫请求模块 request库 json数据_第28张图片
可以通过网站拿免费代理
python爬虫02 - 爬虫请求模块 request库 json数据_第29张图片



import requests
			   #IP           #PORT(端口)
proxy={'http':'182.87.38.117:9000'}
               
url='http://httpbin.org/ip'

res=requests.get(url,proxies=proxy)

print(res.text)

run后结果是
python爬虫02 - 爬虫请求模块 request库 json数据_第30张图片
又试了 好几个还是不行 果然免费的还是不靠谱

4.6 cookie

cookie :通过在客户端记录的信息确定用户身份
HTTP是一种无连接协议,客户端和服务器交互仅仅限于 请求/响应过程,结束后断开,下一次请求时,服务器会认为是一个新的客户端,为了维护他们之间的连接,让服务器知道这是前一个用户发起的请求,必须在一个地方保存客户端信息。
cookie保存在客户端 而session保存在服务器端
我们打开github官网 登录
python爬虫02 - 爬虫请求模块 request库 json数据_第31张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第32张图片
然后关闭该网页
再次打开这个网站
python爬虫02 - 爬虫请求模块 request库 json数据_第33张图片
我们发现没有让我们再次登录 因为我们用户的信息 通过cookie 保存在了客户端 所以 我们再次登录网站会识别cookie

我们再换个网站举例 比如知乎
登录知乎后
在这里插入图片描述
复制热榜中全站的第一个标题
查看网页源代码

python爬虫02 - 爬虫请求模块 request库 json数据_第34张图片
Ctrl+f 把标题粘贴到右上角的框中

python爬虫02 - 爬虫请求模块 request库 json数据_第35张图片
源代码中有该标题 说明当前页面就是这个源代码通过浏览器渲染出来的
我们学cookie 的用处
一 模拟登陆
二 反爬


#我们学cookie 的用处

#一 模拟登陆
import requests
url='https://www.zhihu.com/hot'
res=requests.get(url)

print(res.text)
#二 反爬

如果源码中有这些数据 则证明我们登录成功了
python爬虫02 - 爬虫请求模块 request库 json数据_第36张图片
run一下
python爬虫02 - 爬虫请求模块 request库 json数据_第37张图片
很明显没有成功
可以添加请求头


#我们学cookie 的用处

#一 模拟登陆
import requests
import random

headers_list = [
            {'User-Agent': 'Mozilla/5.0.html (Windows NT 6.1; WOW64) '},
            {'User-Agent': 'AppleWebKit/537.36 (KHTML, like Gecko)'},
            {'User-Agent': 'Chrome/39.0.html.2171.71 Safari/537.36'},
            {'User-Agent': 'Mozilla/5.0.html (X11; Linux x86_64) '},
            {'User-Agent': 'AppleWebKit/537.11 (KHTML, like Gecko) '},
            {'User-Agent': 'Chrome/23.0.html.1271.64 Safari/537.11'},
            {'User-Agent': 'Mozilla/5.0.html (Windows; U; Windows NT 6.1; en-US)'},
            {'User-Agent': 'AppleWebKit/534.16 (KHTML, like Gecko)'},
            {'User-Agent': ' Chrome/10.0.html.648.133 Safari/534.16'}]
headers=random.choice(headers_list)

url='https://www.zhihu.com/hot'
res=requests.get(url,headers=headers)

print(res.text)
#二 反爬

python爬虫02 - 爬虫请求模块 request库 json数据_第38张图片
我们拿到的这个文本数据处于一个没有登录的状态 当你输入www.zhihu.com 它会临时重定向一个页面让你登录 知乎跟其他如 csdn 简书 不同 不登录是没法看到首页的
我们再次回到已经登录好的知乎首页 检查 network 中重新加载 点击 左上角 hot

python爬虫02 - 爬虫请求模块 request库 json数据_第39张图片
找到cookie
python爬虫02 - 爬虫请求模块 request库 json数据_第40张图片


#我们学cookie 的用处

#一 模拟登陆
import requests


headers = {'User-Agent': 'Mozilla/5.0.html (Windows NT 6.1; WOW64) ','cookie':'_xsrf=1SMkDEbBof93pTCRd5MmPz8cmmOuAsaU; _zap=3a8fd847-c5d4-45cf-84a3-24d508f580f6; _ga=GA1.2.2058930090.1594280819; d_c0="AICeuVa2jBGPTuvzpsC3VFkq3TulCqxCfNQ=|1594280816"; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1594280819,1594472555,1594901189; _gid=GA1.2.1424998048.1594901190; SESSIONID=N8kg63Tsh3lZGMF6vI5Fc4gl1B5dIOcyaU6UmrlNRqC; JOID=UVETAkt1itLQrDzMQ3dDxdpur0pXMb2-tpkFlzces7GN6nKAerbAxI2lOcRFiilFl3XWVmgBvZbqyLeAR5S01Rk=; osd=Vl0SBE9yhtPWqDvAQnFHwtZvqU5QPby4sp4JljEatL2M7HaHdrfGwIqpOMJBjSVEkXHRWmkHuZHmybGEQJi10x0=; capsion_ticket="2|1:0|10:1594901205|14:capsion_ticket|44:YWM2MTNmYTg1ODIzNDQwMzhiNTAwODIwNjc0NzRjZWQ=|a77fc810e5b1b898bb505e067a80d273d6f10bc1e3d44581314a9a6d621a78a8"; z_c0="2|1:0|10:1594901209|4:z_c0|92:Mi4xRjdYeENBQUFBQUFBZ0o2NVZyYU1FU1lBQUFCZ0FsVk4yWkQ5WHdBbzV5TkZwYUs4a0RpNWdRUms2Yy1OQlRkaER3|3e67794db7e5f5ec768144d12fdac5ddf9be6d575cf0da3081bd59c5fd132558"; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1594901211; tst=h; tshl=; KLBRSID=b33d76655747159914ef8c32323d16fd|1594901257|1594901188'}


url='https://www.zhihu.com/hot'
res=requests.get(url,headers=headers)

print(res.text)

python爬虫02 - 爬虫请求模块 request库 json数据_第41张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第42张图片
你发现和刚才的明显不一样 了
二 反爬
先打开一个网站12306
python爬虫02 - 爬虫请求模块 request库 json数据_第43张图片
这个流程是先查票查完票再登录
我们首先得拿到一个车次信息
在这里插入图片描述
那么我们要拿到车次信息需要拿到 需要拿到这个url吗(其实拿取车次信息跟这个url是没有联系的)
在这里插入图片描述

#二 反爬
import requests
url='https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
res=requests.get(url)
print(res.text)
run一下

而需要获得到的数据(车次)明显不是在这个url中
页面是由这个源代码通过浏览器渲染出来的 所以我们车次的数据在网页源代码中都有
在当前页面查看网页源代码
输入车次G2195 源代码中却没有这个数据
python爬虫02 - 爬虫请求模块 request库 json数据_第44张图片
我们知道页面是由这个源代码通过浏览器渲染出来的
----那么为什么网页中有的数据为什么网页的源代码中没有呢?
----那么这些数据我们该如何找出来呢?
当我们的从12306发起一个请求给 服务器时 服务器会把数据返回给客户端(浏览器) 但是有的时候会有出现特殊情况 当我们的客户端对服务器多次发起请求的时候 我们就没法确定每一次传输的内容是什么
一般情况 我们可以通过网络源码 可以看服务器给浏览器传递了什么数据 但是发起多次请求时就无法确定了
因为源码的url 它只能接受源码的这些数据
python爬虫02 - 爬虫请求模块 request库 json数据_第45张图片
再有的数据就不会显示在源码当中了 从这个url也就没法查看到了
所以我我们发现在网页中有的数据在网页源代码中没有 而且我们用这个url
https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc 发起请求拿到的数据也是不对的 那么有可能就是服务器多次传输
而且我们会发现一个细节 这个车次列表是本来就没有的 当我们点击查询过后 才出现了车次列表的
python爬虫02 - 爬虫请求模块 request库 json数据_第46张图片
我们尝试用抓包工具找一下
google浏览器打开检查 network 首先要刷新浏览器页面
我们发现刷新过后这个页面又变成了最原始的样子
python爬虫02 - 爬虫请求模块 request库 json数据_第47张图片
此时先清空 clear
python爬虫02 - 爬虫请求模块 request库 json数据_第48张图片
点击clear后 再点击查询
那么就会出现
python爬虫02 - 爬虫请求模块 request库 json数据_第49张图片
点击query(查询的意思)
python爬虫02 - 爬虫请求模块 request库 json数据_第50张图片
在preview中
这个数据就靠谱多了
python爬虫02 - 爬虫请求模块 request库 json数据_第51张图片
而result中0到11 这12行
我们仔细观察
其中有预定
python爬虫02 - 爬虫请求模块 request库 json数据_第52张图片
且在第0行中找到了车次列表中的第一行
在这里插入图片描述
在这里插入图片描述
那么这个数据就对得上了
那么拿去这个数据 则需要 query对应的url

在这里插入图片描述

或者是 copy link address
python爬虫02 - 爬虫请求模块 request库 json数据_第53张图片


#二 反爬
import requests
#为什么网页中有的数据为什么源代码中没有呢

#那么这些数据我们该如何找出来

url='https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2020-08-12&leftTicketDTO.from_station=CDW&leftTicketDTO.to_station=CSQ&purpose_codes=ADULT'
res=requests.get(url)
print(res.content.decode('utf-8'))
run后结果是

python爬虫02 - 爬虫请求模块 request库 json数据_第54张图片
网络可能存在问题 找了半天没有车次数据 说明被反爬了
我们在headers中加入user-agent

#二 反爬
import requests
#为什么网页中有的数据为什么源代码中没有呢

#那么这些数据我们该如何找出来
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}
url='https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2020-08-12&leftTicketDTO.from_station=CDW&leftTicketDTO.to_station=CSQ&purpose_codes=ADULT'
res=requests.get(url,headers=headers)
print(res.content.decode('utf-8'))

然而结果还是被反爬了
python爬虫02 - 爬虫请求模块 request库 json数据_第55张图片
我们要的html应该是在这里插入图片描述
这个一点都不一样
那么我们把这个cookie加上试试 当然此处的Cookie 首字母大写了 (上次知乎的是小写的cookie) 这个的大小写根据网站的变化来定


#二 反爬
import requests
#为什么网页中有的数据为什么源代码中没有呢

#那么这些数据我们该如何找出来
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36','Cookie: _uab_collina=159713069371831632863661; JSESSIONID=9E5B8DDC57337C88476F6D365F4B3BA8; RAIL_EXPIRATION=1597462110322; RAIL_DEVICEID=BojZvbgslGHQgGQCbXBFX5gZFgRKGwnavcD2Ce9WFqUaTaXwQv7gPq-h2z-SRz7I8RKKBHUidE-C06l5kbN3a-y2iEFrxTAnUgacvy0y7tMC5_txxv9wH30IDoYCT6bPu9z7EULYfgPHiduDWyLfdRGT4fWmcn5N; BIGipServerpool_passport=351076874.50215.0000; route=6f50b51faa11b987e576cdb301e545c4; BIGipServerotn=351273482.38945.0000; _jc_save_fromStation=%u6210%u90FD%2CCDW; _jc_save_toStation=%u957F%u6C99%2CCSQ; _jc_save_toDate=2020-08-11; _jc_save_fromDate=2020-08-12; _jc_save_wfdc_flag=dc'}
url='https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2020-08-12&leftTicketDTO.from_station=CDW&leftTicketDTO.to_station=CSQ&purpose_codes=ADULT'
res=requests.get(url,headers=headers)
print(res.content.decode('utf-8'))


{"httpstatus":200,"data":{"result":["nQD5R6eJKtDrnHLa3pfJRVmQTOpnjVfReq3FyK3I2TZ2AChjacE6%2BPFGfUjiTr4%2Bb1c3kA8GC6%2BA%0AmhnSmm82ZJ3t%2FJQRUpztOne%2BX21t%2Btv41RkSPp76P28fyiytRLNrkA4RhNTMsToTopYY9ZN4qesc%0A6medUEyZ9FzK6zfleSAXXDO%2BpIGJmXnks9RsbFsF3TbLbXV1T0YXGBMKLC7HyyQD5uTuXhR3J%2BAq%0Ak2Fyo%2F2G5TWeWSExq0YAuur7po6xHSakYICB%2Flp8cPnaF0%2FBwvLJViZ4UYaH8q3ipivj6iuhskqi%0A|预订|76000G218301|G2183|ICW|CWQ|ICW|CWQ|16:30|23:35|07:05|N|8S7r8rY5keqHYWuVGngN1uNifxX4BkJNkRTzv9z%2BXWdmC1U7|20200812|3|W3|01|12|1|0||||||无|||||无|无|||O0P0M0|OPM|1|1||O057850000P107500000M095200000||||||1|0"],"flag":"1","map":{"ICW":"成都东","CWQ":"长沙南"}},"messages":"","status":true}

python爬虫02 - 爬虫请求模块 request库 json数据_第56张图片
这回数据就对了

类似的反爬比如百度 多次请求百度 会弹出百度安全验证 当你把cookie加上去后就依然能继续请求了
其实headers中 尽可能多加写 爬取成功几率会增加的 user-agent (用户代理) cookie refer 在加上的其实也见得是加上就能爬取到了 基本上就是这3个

4.7 session

session :通过在服务端记录的信息确定用户身份 这里这个session就指的是会话
这个session 不是web中的session 是请求模块中的session

保持会话
session是指从我们打开一个网站开始至我们关闭浏览器一系列的请求过程。比如我们打开淘宝网站,淘宝网站的服务器就会为我们创建并保存一个会话对象,会话对象里有用户的一些信息,比如我们登陆之后,会话中就保存着我们的账号信息。会话有一定的生命周期,当我们长时间(超过会话有效期)没有访问该网站或者关闭浏览器,服务器就会删掉该会话对象。 cookies是指网站为了辨别用户身份,进行会话跟踪而储存在本地终端的数据,cookies一般再电脑中的文件里以文本形式储存。

4.711 session操作

我们可以拿12306这个网站来做个案例
python爬虫02 - 爬虫请求模块 request库 json数据_第57张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第58张图片
12306是2012年推出的实名制买票网站 每天点击量有10亿之多 尤其是过年放假
所以上面 的东西确实可以去降低服务器的压力

我们先输入账号 错误的密码 输入错误的验证码
python爬虫02 - 爬虫请求模块 request库 json数据_第59张图片

再输入正确的验证码
python爬虫02 - 爬虫请求模块 request库 json数据_第60张图片

 session 保持会话
 攻克图片验证码
{'result_message': "验证码校验成功",'result_code': "4"}
 只要控制台打印这个  就代表验证码校验成功了

我们会发现输入账号 错误的密码 输入正确的验证码比错误的明显多了写东西 最主要的变化是多有了login请求
python爬虫02 - 爬虫请求模块 request库 json数据_第61张图片
可以发现这个网站一定是先会去校验的你的验证码 你的验证码校验成功之后才会 才会请求你的账号密码 你的验证码校验失败 网站是不会请求你的账号和密码的


#攻克图片验证码
#{‘result_message’: “验证码校验成功”,‘result_code’: “4”}
#只要控制台打印这个 就代表验证码校验成功了
#1. 目标url
#2.拿到验证码图片
#3.判断哪些图片是正确的

python爬虫02 - 爬虫请求模块 request库 json数据_第62张图片
就是这个url 这是一个get请求 但是我们得用post请求 因为还得要提交下数据 图片验证码的坐标
我们仅需这个url前面的https://kyfw.12306.cn/passport/captcha/captcha-check 就够了
在这里插入图片描述
后面还有很多参数 参数都在下面的Query String Parameters
python爬虫02 - 爬虫请求模块 request库 json数据_第63张图片
在这里插入图片描述
也就是最后一个参数时间戳不用提交 rand 和 login_site 是固定 的 关键是参数坐标值answer 来找到哪个是该找的图片
而且它用的是get请求 我们就不用了 我们用post请求
先复制上面的url 在用pycharm进行操作

我的操作有点相反 是前面第一次是验证码输入正确的(有login请求) 后面几次输入失败的 是没有login请求的
python爬虫02 - 爬虫请求模块 request库 json数据_第64张图片


# session 保持会话

# 攻克图片验证码
# {'result_message': "验证码校验成功",'result_code': "4"}
# 只要控制台打印这个  就代表验证码校验成功了
import requests
import random     (当然这个是完全可以不用的 只是多了一个在请求头列表中随机获取请求头操作而已)
headers_list = [{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'}]
headers=random.choice(headers_list)
#1. 目标url
def login():
    # 数据  Query String Parameters 中的3个参数
    # 别把data写成date了..
    data={'answer': '118,126,8,133','rand': 'sjrand','login_site': 'E'}
    response=requests.post('https://kyfw.12306.cn/passport/captcha/captcha-check',data=data,headers=headers)

    print(response)
#2.拿到验证码图片

#3.判断哪些图片是正确的

login()

<Response [200]>

直接打印出来是个响应对象 200
所以得print(response.text)


# session 保持会话

# 攻克图片验证码
# {'result_message': "验证码校验成功",'result_code': "4"}
# 只要控制台打印这个  就代表验证码校验成功了
import requests
import random
headers_list = [{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'}]
headers=random.choice(headers_list)
#1. 目标url
def login():
    # 数据  Query String Parameters 中的3个参数
    # 别把data写成date了..
    data={'answer': '118,126,8,133','rand': 'sjrand','login_site': 'E'}
    response=requests.post('https://kyfw.12306.cn/passport/captcha/captcha-check',data=data,headers=headers)

    print(response.text)
#2.拿到验证码图片

#3.判断哪些图片是正确的

login()


/**/jQuery19108110694752761256_1597840679267({"result_message":"验证码校验失败,信息为空","result_code":"8"});

然后是拿到验证码的图片
拿到图片的url
python爬虫02 - 爬虫请求模块 request库 json数据_第65张图片
在这里插入图片描述
创建新的text.py文件
python爬虫02 - 爬虫请求模块 request库 json数据_第66张图片
这个url也太多了
而随便一张百度的图片
python爬虫02 - 爬虫请求模块 request库 json数据_第67张图片
它url的长度明显比12306网站上的要短很多的
原因是该网站在这里做了一个base64的处理
在这里插入图片描述
导入base64模块 (python自带的模块)
用这个模块中b64decode的这样一个方法解决


import base64

url='data:image/jpg;base64,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'

img_data=base64.b64decode(url)
fn=open('code.png','wb')

fn.write(img_data)
fn.close()

run一下报了这个错误
binascii.Error: Incorrect padding
binascii.错误:填充不正确
python爬虫02 - 爬虫请求模块 request库 json数据_第68张图片
原因 是这些数据信息的是不需要的
把它删掉就好了
在这里插入图片描述
那么删掉后再次就没有什么错误发生了
python爬虫02 - 爬虫请求模块 request库 json数据_第69张图片
其实类似这种情况 你拿数据拿不到的时候就尝试把url前面的data:image/jpg;base64删掉就好
但是上面的那种写法有些臃肿 不符合OTC 不建议用
那么这张图片是怎么出来呢
在这里插入图片描述
在这里插入图片描述
python爬虫02 - 爬虫请求模块 request库 json数据_第70张图片

复制这个request url 打开看看是不是图片链接
https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&1597848725389&callback=jQuery19103491748461618709_1597848712815&_=1597848712817
python爬虫02 - 爬虫请求模块 request库 json数据_第71张图片
打开链接后是一堆除了下面的文字以外 你都看不懂的代码
而且下面还有一个
captcha-image64?login_site=E&module=login&rand=sjr…
开头的这个玩意 再复制它的 request url 打开看看

python爬虫02 - 爬虫请求模块 request库 json数据_第72张图片
果然跟上面的一样的效果 是一堆看不懂的代码 但是两者的request url 是有些小地方数字不一样
python爬虫02 - 爬虫请求模块 request库 json数据_第73张图片

'https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&1597848719229&callback=jQuery19103491748461618709_1597848712815&_=1597848712816'

'https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&1597848725389&callback=jQuery19103491748461618709_1597848712815&_=1597848712817'

# 两条url的相同部分
'https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand'

打开相同部分
python爬虫02 - 爬虫请求模块 request库 json数据_第74张图片
只需将相同url中的 64 去掉 就获得了图片验证码的链接
在这里插入图片描述
https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand
python爬虫02 - 爬虫请求模块 request库 json数据_第75张图片
我们再回到session.py中


# session 保持会话

# 攻克图片验证码
# {'result_message': "验证码校验成功",'result_code': "4"}
# 只要控制台打印这个  就代表验证码校验成功了
import requests
import random
headers_list = [{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'}]
headers=random.choice(headers_list)
#1. 目标url
def login():

    # 2.拿到验证码图片   传入刚才获得的图片验证码url
    pic_response=requests.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')
    codeimage=pic_response.content
    fn=open('codeee.png','wb')
    fn.write(codeimage)
    fn.close()
    # 数据  Query String Parameters 中的3个参数
    # 别把data写成date了..
    data={'answer': '118,126,8,133','rand': 'sjrand','login_site': 'E'}
    response=requests.post('https://kyfw.12306.cn/passport/captcha/captcha-check',data=data,headers=headers)
    #print(response.text)

#3.判断哪些图片是正确的

login()

python爬虫02 - 爬虫请求模块 request库 json数据_第76张图片


# session 保持会话

# 攻克图片验证码
# {'result_message': "验证码校验成功",'result_code': "4"}
# 只要控制台打印这个  就代表验证码校验成功了
import requests
import random
headers_list = [{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'},{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'}]
headers=random.choice(headers_list)
#1. 目标url
def login():

    # 2.拿到验证码图片   传入刚才获得的图片验证码url
    pic_response=requests.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')
    codeimage=pic_response.content
    fn=open('codeee.png','wb')
    fn.write(codeimage)
    fn.close()
    # 3.判断哪些图片是正确的
    codeStr=input('请输入验证码坐标:')

    # 数据  Query String Parameters 中的3个参数
    # 别把data写成date了..
    data={'answer': codeStr,'rand': 'sjrand','login_site': 'E'}
    response=requests.post('https://kyfw.12306.cn/passport/captcha/captcha-check',data=data,headers=headers)
    
    print(response.text)
login()

而且重复运行我们的codeee.png是会变化的

python爬虫02 - 爬虫请求模块 request库 json数据_第77张图片
run一下 再打开codeee.png 从左上角开始截图
python爬虫02 - 爬虫请求模块 request库 json数据_第78张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第79张图片
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回车后还是不对
在这里插入图片描述
怎么回事呢?、
我向一个网站发起一个 请求 那么要保持这个会话状态去做其他的一些事 也就是我们在对图片进行一些操作的时候依然还保持会话

req=requests.session()

那么就用req发起请求
那么得将下面的request 改写为req
python爬虫02 - 爬虫请求模块 request库 json数据_第80张图片

session案例的最终版本

    # 2.拿到验证码图片   传入刚才获得的图片验证码url
    pic_response=req.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')
    codeimage=pic_response.content
    fn=open('codeee.png','wb')
    fn.write(codeimage)
    fn.close()
    # 3.判断哪些图片是正确的
    codeStr=input('请输入验证码坐标:')

    # 数据  Query String Parameters 中的3个参数
    # 别把data写成date了..
    data={'answer': codeStr,'rand': 'sjrand','login_site': 'E'}
    response=req.post('https://kyfw.12306.cn/passport/captcha/captcha-check',data=data,headers=headers)

   # print(response.text)

还是重复的截图操作
其实这个就是手动添加图片坐标 相当与登录时的点击 只要这个坐标在该正确图片内就行
python爬虫02 - 爬虫请求模块 request库 json数据_第81张图片

请输入验证码坐标:187,63,255,54
{"result_message":"验证码校验成功","result_code":"4"}

请输入验证码坐标:187,63,255,54 这个格式与 下图answer中数据点的格式是一样的
python爬虫02 - 爬虫请求模块 request库 json数据_第82张图片
整个案例最重要的3个点
第一个图片url是通过比较 删掉-image64的64 获得的
在这里插入图片描述
第二个 网页中的请求是get请求 但是我们得用post请求 因为还得要提交下数据 图片验证码的坐标
第三个 在12306中操作图片验证码 找坐标的时候 要在保持会话的状态下进行 (req=requests.session()然后就是把原来的request 改写成我们自己定义的变量req)
在这里插入图片描述

会话维持

当客户端浏览器第一次请求服务器时,服务器会再response中设置一个Set-Cookies的字段,用来标记用户的身份,客户端浏览器会把cookies保存起来,cookies中保存的有Session的id信息。当客户端浏览器再次请求该网站时,会把Cookies放在请求头中一起提交给服务器,服务器检查该Cookies即可找到对应的会话是什么,再通过判断会话来辨认用户的状态。 当我们成功登陆网站时,网站会告诉客户端应该设置哪些Cookies信息,以保持登陆状态。如果客户端浏览器传给服务器的cookies无效或者会话过期,可能就会收到错误的响应或者跳转到登陆页面重新登陆。

小小的补充

import random
    def __init__(self):

        headers_list = [
            {'User-Agent': 'Mozilla/5.0.html (Windows NT 6.1; WOW64) '},
            {'User-Agent': 'AppleWebKit/537.36 (KHTML, like Gecko)'},
            {'User-Agent': 'Chrome/39.0.html.2171.71 Safari/537.36'},
            {'User-Agent': 'Mozilla/5.0.html (X11; Linux x86_64) '},
            {'User-Agent': 'AppleWebKit/537.11 (KHTML, like Gecko) '},
            {'User-Agent': 'Chrome/23.0.html.1271.64 Safari/537.11'},
            {'User-Agent': 'Mozilla/5.0.html (Windows; U; Windows NT 6.1; en-US)'},
            {'User-Agent': 'AppleWebKit/534.16 (KHTML, like Gecko)'},
            {'User-Agent': ' Chrome/10.0.html.648.133 Safari/534.16'}]
        self.headers = random.choice(headers_list)  随机选择请求头列表中的请求头
        self.baseurl = 'https://tieba.baidu.com/f?'

快速双击空行
python爬虫02 - 爬虫请求模块 request库 json数据_第83张图片

4.8 处理不信任的SSL证书

什么是SSL证书?
• SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书。SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能

比如我们有时候工作时就得访问不信任的ssl证书来干点事
https://inv-veri.chinatax.gov.cn/

在这里插入图片描述

import requests

url='https://inv-veri.chinatax.gov.cn/'

res=requests.get(url)
print(res.text)



python爬虫02 - 爬虫请求模块 request库 json数据_第84张图片
不是代码有问题 而是这个网址是浏览器证书风险的 (不信任的sll证书)

而且就算你打开了 https://inv-veri.chinatax.gov.cn/
用360浏览器 但是pycharm还是访问不到的.

import requests

url='https://inv-veri.chinatax.gov.cn/'

res=requests.get(url,verify=False)  verify就是验证  核实的意思 而verify=False就是不需要再核实鉴别的意思了
 

print(res.content.decode('utf-8'))
run后这样就可以访问到了  这个网页 html的文件

requests快速入门(操作)

import requests

#发起请求
response=requests.get('https://www.baidu.com/?tn=88093251_34_hao_pg')

#获取响应对象

print(response)

<Response [200]>      只要是这个<  > 尖括号  它就是个对象



print(response,type(response))

<Response [200]> <class 'requests.models.Response'>

按住CTRL键点击get
python爬虫02 - 爬虫请求模块 request库 json数据_第85张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第86张图片
我们可以构建请求头 传递参数

import requests

#https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}

wd={'wd':'中国'}
#发起请求
response=requests.get('https://www.baidu.com/s?',params=wd,headers=headers)

#获取响应对象

print(response)

<Response [200]>
import requests

#https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}

wd={'wd':'中国'}
#发起请求
response=requests.get('https://www.baidu.com/s?',params=wd,headers=headers)

#获取响应对象

print(response.text)


若是
print(type(response.text))

<class 'str'>

python爬虫02 - 爬虫请求模块 request库 json数据_第87张图片

import requests

#https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}

wd={'wd':'中国'}
#发起请求
response=requests.get('https://www.baidu.com/s?',params=wd,headers=headers)

#获取响应对象

# print(type(response.text))   

print(response.content,type(response.content))

python爬虫02 - 爬虫请求模块 request库 json数据_第88张图片
在这里插入图片描述

<class 'bytes'>

response.content与response.text

假如你这个数据 是一个音乐 图片 视频 那就要返回一个二进制字节流数据就用(response.content )
假如 数据是一个网页源码 html文件 就得返回一个字符串类型的数就用(response.text)
response.text
也就是说可以这样动态的添加网址(图片二进制数据也是可以)
response=requests.get(‘https://www.baidu.com/s?’,params=wd,headers=headers)

python爬虫02 - 爬虫请求模块 request库 json数据_第89张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第90张图片
也就是上图中response 是一个网页源码 就是一个str类型 直接可以用
python爬虫02 - 爬虫请求模块 request库 json数据_第91张图片
用response.content也可以 就是得response.content.decode( )
python爬虫02 - 爬虫请求模块 request库 json数据_第92张图片
不加.decode()
字节流数据 bytes b’开头 获取到的网页源码就成了乱码
python爬虫02 - 爬虫请求模块 request库 json数据_第93张图片

我们打开一个网址
python爬虫02 - 爬虫请求模块 request库 json数据_第94张图片
https://qq.yh31.com/ql/jy/99120.html

import requests

#https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}

wd={'wd':'中国'}
#发起请求
response=requests.get('https://www.baidu.com/s?',params=wd,headers=headers)

#获取响应对象

# print(type(response.text))   

# print(response.content,type(response.content))  字节流数据   二进制

# print(response.url) #返回请求的url

res=requests.get('https://qq.yh31.com/ql/jy/99120.html')

print(res.text)

我们会发现结果有些乱码
python爬虫02 - 爬虫请求模块 request库 json数据_第95张图片
若换成res.content

res=requests.get('https://qq.yh31.com/ql/jy/99120.html')

print(res.content)

python爬虫02 - 爬虫请求模块 request库 json数据_第96张图片
我们发现还是看不懂的
python爬虫02 - 爬虫请求模块 request库 json数据_第97张图片
这样结果内容才与图片页面的源码一样
python爬虫02 - 爬虫请求模块 request库 json数据_第98张图片
且此时的这行代码中

print(res.content.decode('utf-8'))

content 是一个方法 并不是变量
python爬虫02 - 爬虫请求模块 request库 json数据_第99张图片
我们来说一下为何会产生这个情况
首先text 返回的是一个字符串这没问题 然后呢content返回的是一个字节流数据
那上图中我们加上了.decode 返回来是一个字符串 并且还把乱码问题解决了
因为 res.text虽然看似一步的操作 其实是先用res.content的方法拿到数据 然后再用requests 的其他模块去解码 因为是requests库自己解码所以 可能出现错误 (没有解对) 所以用text方法其实已经就调用了content方法
不如我们直接用content方法手动解码
在这里插入图片描述
所以这一步print(type(res.content.decode('utf-8'))) 是获取数据源代码最保险的一种方式

当然我们还可以加上res.encoding=‘utf-8’

import requests

#https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}

wd={'wd':'中国'}
#发起请求
response=requests.get('https://www.baidu.com/s?',params=wd,headers=headers)

#获取响应对象

# print(type(response.text))   

# print(response.content,type(response.content))  字节流数据   二进制

# print(response.url) #返回请求的url

res=requests.get('https://qq.yh31.com/ql/jy/99120.html')

res.encoding='utf-8'

# print(type(res.content.decode('utf-8')))
print(res.text)

结果也是这个图片的网页源代码 不会出现乱码问题 当然还是建议用第一种

杠精小问题

那res.text.decode(‘utf-8’) 不就也行
python爬虫02 - 爬虫请求模块 request库 json数据_第100张图片
AttributeError: ‘str’ object has no attribute ‘decode’
AttributeError:“str”对象没有属性“decode”

requests模块发送post请求

• response.text 返回unicode格式的数据(str)
• response.content 返回字节流数据(二进制)
• response.content.decode(‘utf-8’) 手动进行解码
• response.url 返回url
• response.encoding=‘编码’

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/8/6 21:35
# @Author  : Lonegly
# @File    : requests模块发送Post请求;额.py
# @Software: PyCharm


import requests
import json
key=input('请输入内容:')

data={
    'i': key,
    'from': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15880623642174',
    'sign': 'c6c2e897040e6cbde00cd04589e71d4e',
    'ts': '1588062364217',
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom':'fanyi.web',
    'action': 'FY_BY_CLICKBUTTION'
}

url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}

res=requests.post(url,data=data,headers=headers)
res.encoding='utf-8'

html=res.text

r_dict=json.loads(html)
r=r_dict['translateResult'][0][0]['tgt']
print(r)
#后面的操作前面 提及 r=r_dict['translateResult'][0][0]['tgt']


请输入内容:好吗好的呀
Good good ah

5. requests 模块源码分析

提高自己
当你的技术提高以后 你需要看一些更好的设计模式以及开发思想 思路
还比如如果公司给你一个框架的源代码3000行 给你3天看完 这时候这种能力就会很重要
打开github官网
直接搜索requests
在这里插入图片描述
python爬虫02 - 爬虫请求模块 request库 json数据_第101张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第102张图片

或者是
python爬虫02 - 爬虫请求模块 request库 json数据_第103张图片
python爬虫02 - 爬虫请求模块 request库 json数据_第104张图片
在这里插入图片描述
复制python爬虫02 - 爬虫请求模块 request库 json数据_第105张图片
不行的话还是老老实实用上面的方法
下载它源码的压缩包
在这里插入图片描述
下载完后 解压 再用pycharm打开它
在这里插入图片描述
前两个先不用看 docs 文档 ext扩展 requests 是核心的文件夹 是我们主要看的
tests 测试的一些东西

6. json数据

JSON 字符串
JSON 中的字符串必须用双引号包围。

实例

{ "name":"John" }

数据提取
什么是数据提取?
简单的来说,数据提取就是从相应中获取我们想要的数据的过程
数据分类
非结构化数据:HTML
处理方法:正则表达式、xpath
结构化数据:json、xml
处理方法:转化为Python数据类型

html 就比如百度页面的源代码 这个结构你看不出来
python爬虫02 - 爬虫请求模块 request库 json数据_第106张图片
json
在这里插入图片描述
xml 以后在介绍
数据提取之json
由于把json数据转化为python内建数据类型很简单,所以爬虫中,如果我们能够找到返回json数据的URL,就会尽量使用这种URL
JSON是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互。
使用json注意点
• json中的字符串都是双引号
python爬虫02 - 爬虫请求模块 request库 json数据_第107张图片
只要是loads dumps (带有s的) 这个数据转化就和字符串有关系
j 变p load(s)

**并且 json.dump()这个方法 必须接收两个参数 只能写入文件
json.load()方法只能接收一个参数 只能读取文件 **
具体可以看看奇怪的现象
python爬虫02 - 爬虫请求模块 request库 json数据_第108张图片

json 操作案例

import json

s='json'

print(s,type(s))#json

#python数据类型 --> json类型的字符串

print(json.dumps(s),type(json.dumps(s)))



json <class 'str'>
"json" <class 'str'>

import json

s='json'

# print(s,type(s))#json 

#python数据类型 --> json类型的字符串

# print(json.dumps(s),type(json.dumps(s)))#"json" 

# python数据类型--->json文件字符串
json.dump(s,open('json.txt','w')) 传入s 就是上面的字符串  然后用open()写入文件

在这里插入图片描述

import json

s='json'

# print(s,type(s))#json 

#python数据类型 --> json类型的字符串

# print(json.dumps(s),type(json.dumps(s)))#"json" 
# python数据类型--->json文件字符串
json.dump(s,open('json.txt','w'))

# json文件字符串--->python数据类型
p=json.load(open('json.txt','r')) r只读
print(p) #json

json

很奇怪的现象

import json

s='json'

# print(s,type(s))#json 

#python数据类型 --> json类型的字符串

# print(json.dumps(s),type(json.dumps(s)))#"json" 
# python数据类型--->json文件字符串
json.dump(s,open('json.txt','w'))
d=open('json.txt','r')
print(d)
# json文件字符串--->python数据类型
# p=json.load(open('json.txt','r'))   
# print(p)   没有办法能和这个一样打印出


<_io.TextIOWrapper name='json.txt' mode='r' encoding='cp936'>

import json

s='json'

# print(s,type(s))#json 

#python数据类型 --> json类型的字符串

# print(json.dumps(s),type(json.dumps(s)))#"json" 
# python数据类型--->json文件字符串
json.dump(s,open('json.txt','w'))
d=json.dump(open('json.txt','r'))
print(d)
# json文件字符串--->python数据类型
# p=json.load(open('json.txt','r'))
# print(p)



TypeError: dump() missing 1 required positional argument: 'fp'
TypeError:dump()缺少1个必需的位置参数:“fp”
import json

s='json'

# print(s,type(s))#json 

#python数据类型 --> json类型的字符串

# print(json.dumps(s),type(json.dumps(s)))#"json" 
# python数据类型--->json文件字符串
json.dump(s,open('json.txt','w'))
d=json.dump(s,open('json.txt','r'))
print(d)
# json文件字符串--->python数据类型
# p=json.load(open('json.txt','r'))
# print(p)


io.UnsupportedOperation: not writable
不支持操作:不可写
import json

s='json'

# print(s,type(s))#json 

#python数据类型 --> json类型的字符串

# print(json.dumps(s),type(json.dumps(s)))#"json" 
# python数据类型--->json文件字符串
json.dump(s,open('json.txt','w'))
d=json.load(s,open('json.txt','r'))
print(d)
# json文件字符串--->python数据类型
# p=json.load(open('json.txt','r'))
# print(p)

TypeError: load() takes 1 positional argument but 2 were given
TypeError:load()接受1个位置参数,但给出了2
import json

s='json'

# print(s,type(s))#json 

#python数据类型 --> json类型的字符串

# print(json.dumps(s),type(json.dumps(s)))#"json" 
# python数据类型--->json文件字符串
json.dump(s,open('json.txt','w'))
d=json.load(open('json.txt','r'))
print(d)
# json文件字符串--->python数据类型
p=json.load(open('json.txt','r'))
print(p)



json
json
import json

s='json'

# print(s,type(s))#json 

#python数据类型 --> json类型的字符串

# print(json.dumps(s),type(json.dumps(s)))#"json" 
# python数据类型--->json文件字符串
# json.dump(s,open('json.txt','w'))
d=json.load(s,open('json.txt','w'))
print(d)
# json文件字符串--->python数据类型
# p=json.load(open('json.txt','r'))
# print(p)

TypeError: load() takes 1 positional argument but 2 were given
TypeError:load()接受1个位置参数,但给出了2

可以看出dump只能写入文件不能读 而load只能读
其原因应该是json.dump()这个方法 必须接收两个参数 json.load()方法只能接收一个参数

小结&复习

python爬虫02 - 爬虫请求模块 request库 json数据_第109张图片

你可能感兴趣的:(python爬虫,python)