1. urllib.request模块
先用之前学到过的方法解决
第一种方法
先创建一个爬取图片.py 在新标签页中打开图片
这就是该图片的url
import requests#图片的urlurl='/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596188551&di=3c06d3cd21c706c6c9c562f2bf76f56e&src=http://a3./14/75/01300000164186121366756803686.jpg'req=requests.get(url)fn=open('code.png','wb')fn.write(req.content)fn.close()
执行后
第二种方法
import requestsurl='/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596188551&di=3c06d3cd21c706c6c9c562f2bf76f56e&src=http://a3./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='/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1596188551&di=3c06d3cd21c706c6c9c562f2bf76f56e&src=http://a3./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('/')print(response)<http.client.HTTPResponse object at 0x0000000002504E20>是一个对象
import urllib.request# 向百度发起一个请求 得到一个响应结果 用一个变量接收response=urllib.request.urlopen('/')#从响应对象中获取数据 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=/"></noscript>\r\n</body>\r\n</html>'咱们拿到的这个response数据应该是网页源码 但是这些太少了
咱们拿到的网页源码应该是这些
上面操作拿到的显然太少了 原因是百度在这里做了反爬了
咱们换个网站 一会再解决这个问题
但是没有文字
因为
这个b bit数据类型 字节
可以查看它的类型
import urllib.request# 向百度发起一个请求 得到一个响应结果 用一个变量接收response=urllib.request.urlopen('/')#从响应对象中获取数据 read()函数来读取数据# print(response.read())html=response.read()print(type(html))<class 'bytes'> 类型是字节
但是现在我想看到的是字符串类型
字节转换成字符串 用解码 decode
import urllib.request# 向百度发起一个请求 得到一个响应结果 用一个变量接收response=urllib.request.urlopen('/')#从响应对象中获取数据 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('/',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='/'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='/'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/
urllib 是python自带的请求模块 request是第三方的请求模块
2. urllib.parse模块
2.1 常用方法
• urlencode(字典) 参数就是字典
• quote(字符串) (这个里面的参数是个字符串)
实际操作0
我们先用百度搜素海贼王
因为是get请求 请求参数会显示在url上
后面的参数我们先不看 我们先拿关键的部分
url='/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解码
/tools/urlencode.aspx
import urllib.parse# url='/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 初始urlbaseurl='/s?'#此处的s?比较重要 不能丢content=input('你要搜索的内容:')wd={'wd':content} #当然也可以是d={'wd':content} 前面的那个变量可以随便编 但是key值就是wb 这个不能错content=urllib.parse.urlencode(wd)#拼接urlurl=baseurl+contentprint(url)你要搜索的内容:美女 #回车 此处可以自行输入内容 /s?wd=%E7%BE%8E%E5%A5%B3
练习之最终版本
# 导入模块import urllib.parseimport urllib.request#在百度上输入一个内容 例如:美女 数据保存到本地文件 美女.html#baseurl 初始urlbaseurl='/s?'#此处的s?比较重要 不能丢content=input('你要搜索的内容:')wd={'wd':content} #当然也可以是d={'wd':content} 前面的那个变量可以随便编 但是key值就是wb 这个不能错content=urllib.parse.urlencode(wd)#拼接urlurl=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='/s?'r={'wd':'海贼王'}result=urllib.parse.urlencode(r)url=baseurl+resultprint(url)/s?wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B
quote(字符串)
quote(引用)
import urllib.parsekey=input('输入内容:')baseurl='/s?wd='r=urllib.parse.quote(key)url=baseurl+rprint(url)输入内容:姑娘/s?wd=%E5%A7%91%E5%A8%98
二者区别应该也就是baseurl中的wd=
练习一爬取百度贴吧
需求: 1输入要爬取贴吧的主题 2输入爬取的起始页和终止页 3把每一页的内容保存到本地
我们可以去网上搜索一些请求头
需求: 1输入要爬取贴吧的主题 2输入爬取的起始页和终止页 3把每一页的内容保存到本地分析/f?kw=%E4%B8%AD%E5%9B%BD&ie=utf-8&pn=0 第一页/f?kw=%E4%B8%AD%E5%9B%BD&ie=utf-8&pn=50 第二页/f?kw=%E4%B8%AD%E5%9B%BD&ie=utf-8&pn=100 第三页pn=(当前页数-1)*50kw 贴吧的主题import randomimport urllib.requestimport 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/0101 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='/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.requestimport 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 = '/f?'url = baseurl + kw + '&pn=' + str(pn) # 因为这是一个字符串的拼串filename = '第' + str(i) + '页%s贴吧.html' % namehtml=readPage(url)writePage(filename,html)if __name__ == '__main__':main()
练习三爬取百度贴吧(引入类)
import urllib.requestimport 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 = '/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 = '/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地址是可以帮我们做这个翻译的
就是
中的
/translate_o?smartresult=dict&smartresult=rule
然后我们的输入内容会在form表单里面 这个表单里有些数据是变的 有些数据是不变的
你会发现这里面特别像字典 key-value
我们先把他们全部拿下来 复制 那么我们就可以把form表单里 的数据变成一个字典
然后再把这个字典类的数据以post的方式提交到上面说的url地址上
但是提交的时候我们用的是urllib 用其中的方法request.Request( ) 但是用它的额话 提交的数据得是一个字节 那么我们就得把字典数据类型转化成字节流
import urllib.parseimport 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='/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=‘/translate_o?smartresult=dict&smartresult=rule’
我们把_o去掉
url中去掉 _o
import urllib.parseimport 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='/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.parseimport urllib.requestimport 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='/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.parseimport urllib.requestimport 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='/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参数就可以了
• 代理网站
快代理:/
代理云:/
request设置代理
测试请求头网址: /user-agent
可以通过网站拿免费代理
import requests#IP #PORT(端口)proxy={'http':'182.87.38.117:9000'}url='/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 requestsurl='/hot'res=requests.get(url)print(res.text)#二 反爬
如果源码中有这些数据 则证明我们登录成功了
run一下
很明显没有成功
可以添加请求头
#我们学cookie 的用处#一 模拟登陆import requestsimport 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='/hot'res=requests.get(url,headers=headers)print(res.text)#二 反爬
我们拿到的这个文本数据处于一个没有登录的状态 当你输入 它会临时重定向一个页面让你登录 知乎跟其他如 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='/hot'res=requests.get(url,headers=headers)print(res.text)
你发现和刚才的明显不一样 了
二 反爬
先打开一个网站12306
这个流程是先查票查完票再登录
我们首先得拿到一个车次信息
那么我们要拿到车次信息需要拿到 需要拿到这个url吗(其实拿取车次信息跟这个url是没有联系的)
#二 反爬import requestsurl='/otn/leftTicket/init?linktypeid=dc'res=requests.get(url)print(res.text)run一下
而需要获得到的数据(车次)明显不是在这个url中
页面是由这个源代码通过浏览器渲染出来的 所以我们车次的数据在网页源代码中都有
在当前页面查看网页源代码
输入车次G2195 源代码中却没有这个数据
我们知道页面是由这个源代码通过浏览器渲染出来的
----那么为什么网页中有的数据为什么网页的源代码中没有呢?
----那么这些数据我们该如何找出来呢?
当我们的从12306发起一个请求给 服务器时 服务器会把数据返回给客户端(浏览器) 但是有的时候会有出现特殊情况 当我们的客户端对服务器多次发起请求的时候 我们就没法确定每一次传输的内容是什么
一般情况 我们可以通过网络源码 可以看服务器给浏览器传递了什么数据 但是发起多次请求时就无法确定了
因为源码的url 它只能接受源码的这些数据
再有的数据就不会显示在源码当中了 从这个url也就没法查看到了
所以我我们发现在网页中有的数据在网页源代码中没有 而且我们用这个url
/otn/leftTicket/init?linktypeid=dc 发起请求拿到的数据也是不对的 那么有可能就是服务器多次传输
而且我们会发现一个细节 这个车次列表是本来就没有的 当我们点击查询过后 才出现了车次列表的
我们尝试用抓包工具找一下
google浏览器打开检查 network 首先要刷新浏览器页面
我们发现刷新过后这个页面又变成了最原始的样子
此时先清空 clear
点击clear后 再点击查询
那么就会出现
点击query(查询的意思)
在preview中
这个数据就靠谱多了
而result中0到11 这12行
我们仔细观察
其中有预定
且在第0行中找到了车次列表中的第一行
那么这个数据就对得上了
那么拿去这个数据 则需要 query对应的url
或者是 copy link address
#二 反爬import requests#为什么网页中有的数据为什么源代码中没有呢#那么这些数据我们该如何找出来url='/otn/leftTicket/query?leftTicketDTO.train_date=-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='/otn/leftTicket/query?leftTicketDTO.train_date=-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=-08-11; _jc_save_fromDate=-08-12; _jc_save_wfdc_flag=dc'}url='/otn/leftTicket/query?leftTicketDTO.train_date=-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||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是推出的实名制买票网站 每天点击量有10亿之多 尤其是过年放假
所以上面 的东西确实可以去降低服务器的压力
我们先输入账号 错误的密码 输入错误的验证码
再输入正确的验证码
session 保持会话攻克图片验证码{'result_message': "验证码校验成功",'result_code': "4"}只要控制台打印这个 就代表验证码校验成功了
我们会发现输入账号 错误的密码 输入正确的验证码比错误的明显多了写东西 最主要的变化是多有了login请求
可以发现这个网站一定是先会去校验的你的验证码 你的验证码校验成功之后才会 才会请求你的账号密码 你的验证码校验失败 网站是不会请求你的账号和密码的
#攻克图片验证码
#{‘result_message’: “验证码校验成功”,‘result_code’: “4”}
#只要控制台打印这个 就代表验证码校验成功了
#1. 目标url
#2.拿到验证码图片
#3.判断哪些图片是正确的
就是这个url 这是一个get请求 但是我们得用post请求 因为还得要提交下数据 图片验证码的坐标
我们仅需这个url前面的/passport/captcha/captcha-check 就够了
后面还有很多参数 参数都在下面的Query String Parameters
也就是最后一个参数时间戳不用提交 rand 和 login_site 是固定 的关键是参数坐标值answer来找到哪个是该找的图片
而且它用的是get请求 我们就不用了 我们用post请求
先复制上面的url 在用pycharm进行操作
我的操作有点相反 是前面第一次是验证码输入正确的(有login请求) 后面几次输入失败的 是没有login请求的
# session 保持会话# 攻克图片验证码# {'result_message': "验证码校验成功",'result_code': "4"}# 只要控制台打印这个 就代表验证码校验成功了import requestsimport 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/0101 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. 目标urldef login():# 数据 Query String Parameters 中的3个参数# 别把data写成date了..data={'answer': '118,126,8,133','rand': 'sjrand','login_site': 'E'}response=requests.post('/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 requestsimport randomheaders_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/0101 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. 目标urldef login():# 数据 Query String Parameters 中的3个参数# 别把data写成date了..data={'answer': '118,126,8,133','rand': 'sjrand','login_site': 'E'}response=requests.post('/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 打开看看是不是图片链接
/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 是有些小地方数字不一样
'/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&1597848719229&callback=jQuery19103491748461618709_1597848712815&_=1597848712816''/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&1597848725389&callback=jQuery19103491748461618709_1597848712815&_=1597848712817'# 两条url的相同部分'/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand'
打开相同部分
只需将相同url中的 64 去掉 就获得了图片验证码的链接
/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand
我们再回到session.py中
# session 保持会话# 攻克图片验证码# {'result_message': "验证码校验成功",'result_code': "4"}# 只要控制台打印这个 就代表验证码校验成功了import requestsimport randomheaders_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/0101 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. 目标urldef login():# 2.拿到验证码图片 传入刚才获得的图片验证码urlpic_response=requests.get('/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('/passport/captcha/captcha-check',data=data,headers=headers)#print(response.text)#3.判断哪些图片是正确的login()
# session 保持会话# 攻克图片验证码# {'result_message': "验证码校验成功",'result_code': "4"}# 只要控制台打印这个 就代表验证码校验成功了import requestsimport randomheaders_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/0101 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. 目标urldef login():# 2.拿到验证码图片 传入刚才获得的图片验证码urlpic_response=requests.get('/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('/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('/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('/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 = '/f?'
快速双击空行
4.8 处理不信任的SSL证书
什么是SSL证书?
• SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书。SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能
比如我们有时候工作时就得访问不信任的ssl证书来干点事
https://inv-veri./
import requestsurl='https://inv-veri./'res=requests.get(url)print(res.text)
不是代码有问题 而是这个网址是浏览器证书风险的 (不信任的sll证书)
而且就算你打开了 https://inv-veri./
用360浏览器 但是pycharm还是访问不到的.
import requestsurl='https://inv-veri./'res=requests.get(url,verify=False) verify就是验证 核实的意思 而verify=False就是不需要再核实鉴别的意思了print(res.content.decode('utf-8'))run后这样就可以访问到了 这个网页 html的文件
requests快速入门(操作)
import requests#发起请求response=requests.get('/?tn=88093251_34_hao_pg')#获取响应对象print(response)<Response [200]>只要是这个< > 尖括号 它就是个对象print(response,type(response))<Response [200]> <class 'requests.models.Response'>
按住CTRL键点击get
我们可以构建请求头 传递参数
import requests#/s?wd=%E4%B8%AD%E5%9B%BDheaders={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/0101 Firefox/6.0'}wd={'wd':'中国'}#发起请求response=requests.get('/s?',params=wd,headers=headers)#获取响应对象print(response)<Response [200]>
import requests#/s?wd=%E4%B8%AD%E5%9B%BDheaders={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/0101 Firefox/6.0'}wd={'wd':'中国'}#发起请求response=requests.get('/s?',params=wd,headers=headers)#获取响应对象print(response.text)若是print(type(response.text))<class 'str'>
import requests#/s?wd=%E4%B8%AD%E5%9B%BDheaders={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/0101 Firefox/6.0'}wd={'wd':'中国'}#发起请求response=requests.get('/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(‘/s?’,params=wd,headers=headers)
也就是上图中response 是一个网页源码 就是一个str类型 直接可以用
用response.content也可以 就是得response.content.decode( )
不加.decode()
字节流数据 bytes b’开头 获取到的网页源码就成了乱码
我们打开一个网址
/ql/jy/99120.html
import requests#/s?wd=%E4%B8%AD%E5%9B%BDheaders={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/0101 Firefox/6.0'}wd={'wd':'中国'}#发起请求response=requests.get('/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('/ql/jy/99120.html')print(res.text)
我们会发现结果有些乱码
若换成res.content
res=requests.get('/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#/s?wd=%E4%B8%AD%E5%9B%BDheaders={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/0101 Firefox/6.0'}wd={'wd':'中国'}#发起请求response=requests.get('/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('/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 : /8/6 21:35# @Author : Lonegly# @File : requests模块发送Post请求;额.py# @Software: PyCharmimport requestsimport jsonkey=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='/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 givenTypeError: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)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=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 givenTypeError:load()接受1个位置参数,但给出了2个
可以看出dump只能写入文件不能读 而load只能读
其原因应该是json.dump()这个方法 必须接收两个参数 json.load()方法只能接收一个参数
小结&复习
如果觉得《python爬虫02 - 爬虫请求模块 request库 json数据》对你有帮助,请点赞、收藏,并留下你的观点哦!