1. urllib.request模块

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

第一种方法

先创建一个爬取图片.py 在新标签页中打开图片

这就是该图片的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()

执行后

第二种方法

import requestsurl='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)

第三种方法

import requestsfrom urllib import requesturl='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)

运行一下

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'<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.replace("https://","http://"));\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>'
咱们拿到的这个response数据应该是网页源码  但是这些太少了

咱们拿到的网页源码应该是这些

上面操作拿到的显然太少了 原因是百度在这里做了反爬了
咱们换个网站 一会再解决这个问题



但是没有文字
因为
这个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)

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

咱们再来搞一搞刚才百度的反爬 可能是我们没有添加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)


这就和用谷歌浏览器打开的百度源码页内容一样了

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

我们先用百度搜素海贼王

因为是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


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.parseimport 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+contentprint(url)你要搜索的内容:美女 #回车   此处可以自行输入内容
https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3

练习之最终版本

# 导入模块
import urllib.parseimport 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+contentheaders = {'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)

小结

反爬 ua refer cookie 可以把这些添加进去来反制一些反爬

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

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

urlencode(字典)

import urllib.parsebaseurl='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.parsekey=input('输入内容:')baseurl='https://www.baidu.com/s?wd='r=urllib.parse.quote(key)url=baseurl+rprint(url)输入内容:姑娘
https://www.baidu.com/s?wd=%E5%A7%91%E5%A8%98

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

练习一爬取百度贴吧


需求:
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-agentheaders_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):#开始拼接urlpn=(i-1)*50baseurl='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'%namewith 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):# 开始拼接urlpn = (i - 1) * 50baseurl = 'https://tieba.baidu.com/f?'url = baseurl + kw + '&pn=' + str(pn)  # 因为这是一个字符串的拼串filename = '第' + str(i) + '页%s贴吧.html' % namehtml=readPage(url)writePage(filename,html)
if __name__ == '__main__':main()

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

import urllib.request
import urllib.parseclass 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 htmldef 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):# 开始拼接urlpn = (i - 1) * 50# baseurl = 'https://tieba.baidu.com/f?'这个就不用了url = self.baseurl + kw + '&pn=' + str(pn)  # 因为这是一个字符串的拼串filename = '第' + str(i) + '页%s贴吧.html' % namehtml = 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

案例思路



就是比如图中的你好 这些数据 以post请求提交给服务器 提交到了form表单.


提交是手动提交的 我们可以做一个有道翻译小软件.
首先这个请求的url地址是可以帮我们做这个翻译的
就是
中的
http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
然后我们的输入内容会在form表单里面 这个表单里有些数据是变的 有些数据是不变的
你会发现这里面特别像字典 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
原因就是

而控制台打印的结果 它会把引号省去

所以这个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是一个列表 我们的目标是取到此列表中的列表中的字典的值
所以

于是乎 可以有了更简单直接的方法

有道字典小程序

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
• 在开发工具中安装

安装可以直接到我们的设置里面

这这里点右上角的加号

左下角的intsall package 安装
如果还是不行的话 我们可以换源安装

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



可以通过网站拿免费代理

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后结果是

又试了 好几个还是不行 果然免费的还是不靠谱

4.6 cookie

cookie :通过在客户端记录的信息确定用户身份
HTTP是一种无连接协议,客户端和服务器交互仅仅限于 请求/响应过程,结束后断开,下一次请求时,服务器会认为是一个新的客户端,为了维护他们之间的连接,让服务器知道这是前一个用户发起的请求,必须在一个地方保存客户端信息。
cookie保存在客户端 而session保存在服务器端
我们打开github官网 登录


然后关闭该网页
再次打开这个网站

我们发现没有让我们再次登录 因为我们用户的信息 通过cookie 保存在了客户端 所以 我们再次登录网站会识别cookie

我们再换个网站举例 比如知乎
登录知乎后

复制热榜中全站的第一个标题
查看网页源代码


Ctrl+f 把标题粘贴到右上角的框中


源代码中有该标题 说明当前页面就是这个源代码通过浏览器渲染出来的
我们学cookie 的用处
一 模拟登陆
二 反爬


#我们学cookie 的用处#一 模拟登陆
import requests
url='https://www.zhihu.com/hot'
res=requests.get(url)print(res.text)
#二 反爬

如果源码中有这些数据 则证明我们登录成功了

run一下

很明显没有成功
可以添加请求头


#我们学cookie 的用处#一 模拟登陆
import requests
import randomheaders_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)
#二 反爬


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


找到cookie


#我们学cookie 的用处#一 模拟登陆
import requestsheaders = {'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)



你发现和刚才的明显不一样 了
二 反爬
先打开一个网站12306

这个流程是先查票查完票再登录
我们首先得拿到一个车次信息

那么我们要拿到车次信息需要拿到 需要拿到这个url吗(其实拿取车次信息跟这个url是没有联系的)

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

而需要获得到的数据(车次)明显不是在这个url中
页面是由这个源代码通过浏览器渲染出来的 所以我们车次的数据在网页源代码中都有
在当前页面查看网页源代码
输入车次G2195 源代码中却没有这个数据

我们知道页面是由这个源代码通过浏览器渲染出来的
----那么为什么网页中有的数据为什么网页的源代码中没有呢?
----那么这些数据我们该如何找出来呢?
当我们的从12306发起一个请求给 服务器时 服务器会把数据返回给客户端(浏览器) 但是有的时候会有出现特殊情况 当我们的客户端对服务器多次发起请求的时候 我们就没法确定每一次传输的内容是什么
一般情况 我们可以通过网络源码 可以看服务器给浏览器传递了什么数据 但是发起多次请求时就无法确定了
因为源码的url 它只能接受源码的这些数据

再有的数据就不会显示在源码当中了 从这个url也就没法查看到了
所以我我们发现在网页中有的数据在网页源代码中没有 而且我们用这个url
https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc 发起请求拿到的数据也是不对的 那么有可能就是服务器多次传输
而且我们会发现一个细节 这个车次列表是本来就没有的 当我们点击查询过后 才出现了车次列表的

我们尝试用抓包工具找一下
google浏览器打开检查 network 首先要刷新浏览器页面
我们发现刷新过后这个页面又变成了最原始的样子

此时先清空 clear

点击clear后 再点击查询
那么就会出现

点击query(查询的意思)

在preview中
这个数据就靠谱多了

而result中0到11 这12行
我们仔细观察
其中有预定

且在第0行中找到了车次列表中的第一行


那么这个数据就对得上了
那么拿去这个数据 则需要 query对应的url

或者是 copy link address


#二 反爬
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后结果是


网络可能存在问题 找了半天没有车次数据 说明被反爬了
我们在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'))

然而结果还是被反爬了

我们要的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}


这回数据就对了

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

4.7 session

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

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

4.711 session操作

我们可以拿12306这个网站来做个案例


12306是2012年推出的实名制买票网站 每天点击量有10亿之多 尤其是过年放假
所以上面 的东西确实可以去降低服务器的压力

我们先输入账号 错误的密码 输入错误的验证码

再输入正确的验证码

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

我们会发现输入账号 错误的密码 输入正确的验证码比错误的明显多了写东西 最主要的变化是多有了login请求

可以发现这个网站一定是先会去校验的你的验证码 你的验证码校验成功之后才会 才会请求你的账号密码 你的验证码校验失败 网站是不会请求你的账号和密码的


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


就是这个url 这是一个get请求 但是我们得用post请求 因为还得要提交下数据 图片验证码的坐标
我们仅需这个url前面的https://kyfw.12306.cn/passport/captcha/captcha-check 就够了

后面还有很多参数 参数都在下面的Query String Parameters


也就是最后一个参数时间戳不用提交 rand 和 login_site 是固定 的 关键是参数坐标值answer 来找到哪个是该找的图片
而且它用的是get请求 我们就不用了 我们用post请求
先复制上面的url 在用pycharm进行操作

我的操作有点相反 是前面第一次是验证码输入正确的(有login请求) 后面几次输入失败的 是没有login请求的


# 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


创建新的text.py文件

这个url也太多了
而随便一张百度的图片

它url的长度明显比12306网站上的要短很多的
原因是该网站在这里做了一个base64的处理

导入base64模块 (python自带的模块)
用这个模块中b64decode的这样一个方法解决


import base64url='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.错误:填充不正确

原因 是这些数据信息的是不需要的
把它删掉就好了

那么删掉后再次就没有什么错误发生了

其实类似这种情况 你拿数据拿不到的时候就尝试把url前面的data:image/jpg;base64删掉就好
但是上面的那种写法有些臃肿 不符合OTC 不建议用
那么这张图片是怎么出来呢


复制这个request url 打开看看是不是图片链接
https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&1597848725389&callback=jQuery19103491748461618709_1597848712815&_=1597848712817

打开链接后是一堆除了下面的文字以外 你都看不懂的代码
而且下面还有一个
captcha-image64?login_site=E&module=login&rand=sjr…
开头的这个玩意 再复制它的 request url 打开看看


果然跟上面的一样的效果 是一堆看不懂的代码 但是两者的request url 是有些小地方数字不一样

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

打开相同部分

只需将相同url中的 64 去掉 就获得了图片验证码的链接

https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand

我们再回到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.拿到验证码图片   传入刚才获得的图片验证码urlpic_response=requests.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')codeimage=pic_response.contentfn=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()


# 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.拿到验证码图片   传入刚才获得的图片验证码urlpic_response=requests.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')codeimage=pic_response.contentfn=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是会变化的


run一下 再打开codeee.png 从左上角开始截图





回车后还是不对

怎么回事呢?、
我向一个网站发起一个 请求 那么要保持这个会话状态去做其他的一些事 也就是我们在对图片进行一些操作的时候依然还保持会话

req=requests.session()

那么就用req发起请求
那么得将下面的request 改写为req

session案例的最终版本

    # 2.拿到验证码图片   传入刚才获得的图片验证码urlpic_response=req.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')codeimage=pic_response.contentfn=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)

还是重复的截图操作
其实这个就是手动添加图片坐标 相当与登录时的点击 只要这个坐标在该正确图片内就行

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

请输入验证码坐标:187,63,255,54 这个格式与 下图answer中数据点的格式是一样的

整个案例最重要的3个点
第一个图片url是通过比较 删掉-image64的64 获得的

第二个 网页中的请求是get请求 但是我们得用post请求 因为还得要提交下数据 图片验证码的坐标
第三个 在12306中操作图片验证码 找坐标的时候 要在保持会话的状态下进行 (req=requests.session()然后就是把原来的request 改写成我们自己定义的变量req)

会话维持

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

小小的补充

import randomdef __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?'

快速双击空行

4.8 处理不信任的SSL证书

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

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

import requestsurl='https://inv-veri.chinatax.gov.cn/'res=requests.get(url)
print(res.text)


不是代码有问题 而是这个网址是浏览器证书风险的 (不信任的sll证书)

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

import requestsurl='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


我们可以构建请求头 传递参数

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

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))   <class 'str'>print(response.content,type(response.content))


<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)



也就是上图中response 是一个网页源码 就是一个str类型 直接可以用

用response.content也可以 就是得response.content.decode( )

不加.decode()
字节流数据 bytes b’开头 获取到的网页源码就成了乱码

我们打开一个网址

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))   <class 'str'># print(response.content,type(response.content))  <class 'bytes'>字节流数据   二进制# print(response.url) #返回请求的urlres=requests.get('https://qq.yh31.com/ql/jy/99120.html')print(res.text)

我们会发现结果有些乱码

若换成res.content

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


我们发现还是看不懂的

这样结果内容才与图片页面的源码一样

且此时的这行代码中

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

content 是一个方法 并不是变量

我们来说一下为何会产生这个情况
首先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))   <class 'str'># print(response.content,type(response.content))  <class 'bytes'>字节流数据   二进制# print(response.url) #返回请求的urlres=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’) 不就也行

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: PyCharmimport 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.textr_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


或者是



复制
不行的话还是老老实实用上面的方法
下载它源码的压缩包

下载完后 解压 再用pycharm打开它

前两个先不用看 docs 文档 ext扩展 requests 是核心的文件夹 是我们主要看的
tests 测试的一些东西

6. json数据

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

实例

{ "name":"John" }

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

html 就比如百度页面的源代码 这个结构你看不出来

json

xml 以后在介绍
数据提取之json
由于把json数据转化为python内建数据类型很简单,所以爬虫中,如果我们能够找到返回json数据的URL,就会尽量使用这种URL
JSON是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互。
使用json注意点
• json中的字符串都是双引号

只要是loads dumps (带有s的) 这个数据转化就和字符串有关系
j 变p load(s)

**并且 json.dump()这个方法 必须接收两个参数 只能写入文件
json.load()方法只能接收一个参数 只能读取文件 **
具体可以看看奇怪的现象

json 操作案例

import jsons='json'print(s,type(s))#json#python数据类型 --> json类型的字符串print(json.dumps(s),type(json.dumps(s)))json <class 'str'>
"json" <class 'str'>
import jsons='json'# print(s,type(s))#json <class 'str'>#python数据类型 --> json类型的字符串# print(json.dumps(s),type(json.dumps(s)))#"json" <class 'str'># python数据类型--->json文件字符串
json.dump(s,open('json.txt','w')) 传入s 就是上面的字符串  然后用open()写入文件

import jsons='json'# print(s,type(s))#json <class 'str'>#python数据类型 --> json类型的字符串# print(json.dumps(s),type(json.dumps(s)))#"json" <class 'str'>
# python数据类型--->json文件字符串
json.dump(s,open('json.txt','w'))# json文件字符串--->python数据类型
p=json.load(open('json.txt','r')) r只读
print(p) #jsonjson

很奇怪的现象

import jsons='json'# print(s,type(s))#json <class 'str'>#python数据类型 --> json类型的字符串# print(json.dumps(s),type(json.dumps(s)))#"json" <class 'str'>
# 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 jsons='json'# print(s,type(s))#json <class 'str'>#python数据类型 --> json类型的字符串# print(json.dumps(s),type(json.dumps(s)))#"json" <class 'str'>
# 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 jsons='json'# print(s,type(s))#json <class 'str'>#python数据类型 --> json类型的字符串# print(json.dumps(s),type(json.dumps(s)))#"json" <class 'str'>
# 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 jsons='json'# print(s,type(s))#json <class 'str'>#python数据类型 --> json类型的字符串# print(json.dumps(s),type(json.dumps(s)))#"json" <class 'str'>
# 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 jsons='json'# print(s,type(s))#json <class 'str'>#python数据类型 --> json类型的字符串# print(json.dumps(s),type(json.dumps(s)))#"json" <class 'str'>
# 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 jsons='json'# print(s,type(s))#json <class 'str'>#python数据类型 --> json类型的字符串# print(json.dumps(s),type(json.dumps(s)))#"json" <class 'str'>
# 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数据相关推荐

  1. nodejs爬虫,POST请求发送Request Playload格式数据

    nodejs爬虫,POST请求发送Request Playload格式数据. 本文以网易云课堂其中2个POST请求为例,使用request模块实现. 例子1 1.地址: http://study.16 ...

  2. 一木.溪桥学爬虫-03:请求模块urllib、 urllib.request、urllib.parse.urlencode、urllib.parse.quote(str)、.unquote()

    一木.溪桥 在Logic Education跟Jerry学爬虫 07期:Python 爬虫 一木.溪桥学爬虫-03:请求模块urllib. urllib.request.urllib.parse.ur ...

  3. 29-30Python多线程、多线程、使用threading模块创建线程;JSON数据解析、编码为JSON类型转换对应表、Python类型转换对应表、json.dumps与json.loads

    29Python3多线程 多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理. 用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些 ...

  4. python爬虫(一)urllib.request库学习总结

    一.简单介绍 urllib库:是python的内置请求库,常用于网页的请求访问. 包括以下模块: urllib.request 请求模块 urllib.error 异常处理模块 urllib.pars ...

  5. python爬虫小知识: 通过 request库 代理proxies来设置,无法访问问题

    通过 request库 代理proxies来设置 防止封ip后无法访问问题 1.为什么使用代理 2.request 如何设置代理 需要替换里面的代理池 3.设置需要身份认证的代理 4.request ...

  6. 爬虫学习记录3:request库基础用法

    1.request库基础用法 1.1get()及post()对比解析(发送请求) # 百度举例 import requests url = 'https://www.baidu.com/' heade ...

  7. python发post请求json_python request 以json形式发送post请求的正确的姿势

    一个http请求包括三个部分,为别为请求行,请求报头,消息主体,类似以下这样: 请求行,请求报头,消息主题. 以json串提交数据,编码格式: application/json, 必须加上 impor ...

  8. python时间戳_Python-强大的模块功能库-No11

    <Python真好玩,教孩子学编程>小挑战[转载] 第十一章,强大的模块功能库书籍<Python真好玩,教孩子学编程> 书中详细充实地讲解了模块和命名空间,和通过Python在 ...

  9. Spring拦截器获取request请求体中的json数据,并转换成Java对象的解决办法

    1.要被拦截的Controller接口 我们需要一个更新用户信息接口,请求方式为POST,参数类型为对象类型(UserInfo),代码如下: @Resource private UserService ...

  10. Java以post请求发送文件或json数据

    分别给出了post发送文件和json数据的函数,其中使用到了Jackson库来转化Json数据,使用log4j2来打印日记,可自行剔除. public class HttpUtils {static ...

最新文章

  1. 简单粗暴上手TensorFlow 2.0,北大学霸力作,必须人手一册!
  2. 初涉SQL Server性能问题(3/4):列出阻塞的会话
  3. python 结果写入excel_python中如何将测试结果写入到原有的excel表格(二)
  4. csharp OverflowException——超出数值范围会抛出异常
  5. mysql 关联查询_响应时间长?MySQL查询优化教程来了!
  6. 位运算 c语言 头文件 linux,1. 位运算_C语言_C语言入门-Linux C编程一站式学习...
  7. spring 第一天:1015
  8. 命令行下Apache日志统计举例
  9. iOS 转盘动画效果实现
  10. Delphi 与 DirectX 之 DelphiX(82): TDIB.DrawMandelbrot();
  11. JAVA中iterator与add的顺序问题
  12. B2B多商铺初期权限数据库设计
  13. 7-5 华氏度转摄氏度(四舍五入) (5分)
  14. Vue指令概述,v-if与v-show的区别
  15. 小白:关于处理“can't find '__main__' module in ”这个问题的详细处理方式!
  16. Entry name ‘res/layout/test_toolbar.xml‘ collided
  17. PAT乙级 1072 开学寄语
  18. 那些在做固态盘SSD的其实在研究这仨东西
  19. veu中时间转换----element-UI上Date-Picker时间控件
  20. GO 常见环境变量与常用命令

热门文章

  1. java定积分_记录一次定积分实现方法(java)
  2. 5款瞬间复活Win7/8/10工具
  3. python差异性分析_差异性分析
  4. 【计算机组成原理之存储系统】超级详细
  5. 让人糊里糊涂的HTTP、TCP、UDP、Socket
  6. MAC-快捷键打开终端
  7. linux限制syslog大小,c – 如何限制syslog管理的日志文件的总大小?
  8. YApi接口平台-接口挡板
  9. 计算机图形学红绿蓝组合颜色,二、颜色_计算机图形学(部分章节二)_ppt_大学课件预览_高等教育资讯网...
  10. 电脑硬盘怎么分区?C盘/D盘/E盘......快来创建自己的DIY磁盘吧!