python网络操作
基本使用方式
import urllib.request as http
response = http.urlopen("http://www.baidu.com") # 访问url
html = response.read() # 读取返回数据
html = html.decode("utf-8") # 返回数据为2进制的字符串,需要解码
print(html)
打印的是百度的html代码
下载图片
import urllib.request as http
response = http.urlopen("http://placekitten.com/600/500") # 访问这个地址会返回一张jpg图片
img = response.read() # 读取返回数据
with open('cat.jpg', 'wb') as file:
file.write(img)
运行效果:
实战
有道翻译API调用
有道云api调用参考http://ai.youdao.com/docs/doc-trans-api.s#p02
import urllib.request as http
import urllib.parse
import hashlib
import time
# 生成MD5
def md5(str):
# 创建md5对象
hl = hashlib.md5()
# Tips
# 此处必须声明encode
# 否则报错为:hl.update(str) Unicode-objects must be encoded before hashing
hl.update(str.encode(encoding='utf-8'))
return hl.hexdigest()
url = "http://openapi.youdao.com/api"
data = {}
data['q'] = "good" # 要翻译的文本
data['from'] = 'EN' # 语言列表(可设置为auto)
data['to'] = 'zh-CHS' # 语言列表(可设置为auto)
data['appKey'] = '737a1b528a0b1bd3' # 应用申请的key,可在管理控制台查看
data['salt'] = '123' # 随机数
data['sign'] = md5(
data['appKey'] + data['q'] + data[
'salt'] + 'A73ACjRHpYSdDBxNKqypvvkhJe80xKMM') # 签名,appKey+q+salt+应用密钥的MD5值
data = urllib.parse.urlencode(data).encode('utf-8') # python默认编码格式为unicode,这里要转成utf-8
response = http.urlopen(url, data)
result = response.read().decode('utf-8') # 读取返回数据
print(result)
运行结果:
{
"tSpeakUrl": "http://openapi.youdao.com/ttsapi?q=好&langType=zh-CHS&sign=A406F0B74104D2077E00DFA0A64A8A16&salt=1531378824486&voice=4&format=mp3&appKey=737a1b528a0b1bd3",
"web": [{
"value": ["好", "善", "商品"],
"key": "Good"
}, {
"value": ["公共物品", "公益事业", "公共财"],
"key": "public good"
}, {
"value": ["干的出色", "干得好", "好工作"],
"key": "Good Job"
}],
"query": "good",
"translation": ["好"],
"errorCode": "0",
"dict": {
"url": "yddict://m.youdao.com/dict?le=eng&q=good"
},
"webdict": {
"url": "http://m.youdao.com/dict?le=eng&q=good"
},
"basic": {
"us-phonetic": "ɡʊd",
"phonetic": "gʊd",
"uk-phonetic": "gʊd",
"uk-speech": "http://openapi.youdao.com/ttsapi?q=good&langType=en&sign=AC9AACC9E2AEB612E1F732799D63770D&salt=1531378824486&voice=5&format=mp3&appKey=737a1b528a0b1bd3",
"explains": ["n. 好处;善行;慷慨的行为", "adj. 好的;优良的;愉快的;虔诚的", "adv. 好", "n. (Good)人名;(英)古德;(瑞典)戈德"],
"us-speech": "http://openapi.youdao.com/ttsapi?q=good&langType=en&sign=AC9AACC9E2AEB612E1F732799D63770D&salt=1531378824486&voice=6&format=mp3&appKey=737a1b528a0b1bd3"
},
"l": "EN2zh-CHS",
"speakUrl": "http://openapi.youdao.com/ttsapi?q=good&langType=en&sign=AC9AACC9E2AEB612E1F732799D63770D&salt=1531378824486&voice=4&format=mp3&appKey=737a1b528a0b1bd3"
}
有道云翻译api破解(其实主要是讲在请求体中添加header啦,顺便破解)
按照官方文档请求api获取翻译结果很简单,可惜这个是收费的
但是我们可以在网页上,使用有道云在线翻译,无限制的免费的翻译语言,下面我们来尝试破解有道云在线的api接口
首先我们打开浏览器,推荐用chrome,打开有道云翻译的网页
接着我们输入要翻译的文本,比如:fish
打开调试模式,F12切换到调试模式,选择网络,之后点击翻译
可以看到有2个GET请求和1个POST请求
那么之前的api调用,我们封装了data,在python中,如果不传data,则为GET请求,如果传入data,就为POST请求,这里我们选择POST请求
接着选择正文当中的请求正文
可以看到,这里的参数,就是我们之前封装的data,只是多了一些其他额外的参数
我们继续选择标头,可以看到请求的url
那我们仿照之前的做法,试着写代码
import urllib.request as http
import urllib.parse
import hashlib
import time
# 生成MD5
def md5(str):
hl = hashlib.md5()
hl.update(str.encode(encoding='utf-8'))
return hl.hexdigest()
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
data = {
'action': 'FY_BY_CLICKBUTTION',
'client': 'fanyideskweb',
'doctype': 'json',
'from': 'AUTO',
'i': 'fish',
'keyfrom': 'fanyi.web',
'salt': '1531383453664',
'sign': '476eada25ccbca5b4fad4d87f1ec80ec',
'smartresult': 'dict',
'to': 'AUTO',
'typoResult': 'false',
'version': '2.1'
}
response = http.urlopen(url, urllib.parse.urlencode(data).encode('utf-8'))
result = response.read().decode('utf-8') # 读取返回数据
print(result)
看代码似乎没什么问题,但是一运行,就报如下错误
{"errorCode":50}
我们仔细回忆下,在之前的标头下面,还有一个请求标头,其实就是header,是不是因为缺少header导致返回错误码呢,我们尝试在请求中添加header试试
import urllib.request as http
import urllib.parse
import hashlib
import time
# 生成MD5
def md5(str):
hl = hashlib.md5()
hl.update(str.encode(encoding='utf-8'))
return hl.hexdigest()
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
data = {
'action': 'FY_BY_CLICKBUTTION',
'client': 'fanyideskweb',
'doctype': 'json',
'from': 'AUTO',
'i': 'fish',
'keyfrom': 'fanyi.web',
'salt': '1531383453664',
'sign': '476eada25ccbca5b4fad4d87f1ec80ec',
'smartresult': 'dict',
'to': 'AUTO',
'typoResult': 'false',
'version': '2.1'
}
headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN',
# 'Accept-Encoding': 'gzip, deflate',
'Cache-Control': 'no-cache',
'Connection': 'Keep-Alive',
'Content-Length': '204',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=500507281.7589852; [email protected]; JSESSIONID=aaaTgHrZGrr3BdPW8snsw; ___rl__test__cookies=1531383453650; fanyi-ad-closed=1; fanyi-ad-id=46607',
'Host': 'fanyi.youdao.com',
'Origin': 'http://fanyi.youdao.com',
'Referer': 'http://fanyi.youdao.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134',
'X-Requested-With': 'XMLHttpRequest'
}
# 注意header的添加方式
request = http.Request(url, data=urllib.parse.urlencode(data).encode('utf-8'), headers=headers)
response = http.urlopen(request)
result = response.read().decode('utf-8') # 读取返回数据
print(result)
这里我们把'Accept-Encoding': 'gzip, deflate'注释掉了,这句话的意思是本地接收压缩格式的数据,服务器传过来压缩格式gzip的文件,而解压这种gzip文件只能用deflate算法,浏览器能够自动解压,程序却不能自动解压gzip,因此就让服务器传原始文件过来吧,不用压缩了
运行结果:
{
"translateResult": [
[{
"tgt": "鱼",
"src": "fish"
}]
],
"errorCode": 0,
"type": "en2zh-CHS",
"smartResult": {
"entries": ["", "n. 鱼,鱼类\r\n", "vt. 钓鱼,捕鱼;搜寻\r\n", "vi. 捕鱼,钓鱼;用钩捞取\r\n"],
"type": 1
}
}
卧槽,牛逼啊兄弟,然而事情并没有这么简单,当我们把要翻译的内容,fish,改为其他英文,比如want的时候,一夜回到解放前
{"errorCode":50}
第一次fish的时候可以,第二次want就不行,那么能够想到的,就是两次请求,除了翻译的文本不同外,data和header的其他参数有差异,我们在在线翻译的网页上,输入want,点击翻译,再次抓一个包,和第一次的包,对比一下,发现如下不同
现在看来,错误码应该就是由于这几个参数导致的了
"salt"我们之前通过查看官方api文档知道是一个随机数,这里对数字比较敏感的话,应该可以看出来是时间戳
"_rltest__cookies"应该也不难看出来是一个时间戳
关键就是sign,sign我们之前通过官方api文档知道,它是appKey+翻译文本+salt+应用秘钥的MD5值
前面3个我们都有,关键是这个应用秘钥是啥
而MD5目测应该是卸载javascript中的,所以我们这里查看一下js代码
打开fanyi.min.js,将代码用工具格式化一下,因为我们需要知道sign是怎么来的,因此我们全局搜索一下"sign"
看到这里,相信应该都知道,sign是怎么来了吧,没错,应用秘钥就是"ebSeFb%=XZ%T[KZ)c(sy!"
下面我们就可以一起愉快的撸代码了
完整代码:
import urllib.request as http
import urllib.parse
import hashlib
import time
# 生成MD5
def md5(str):
# 创建md5对象
hl = hashlib.md5()
# Tips
# 此处必须声明encode
# 否则报错为:hl.update(str) Unicode-objects must be encoded before hashing
hl.update(str.encode(encoding='utf-8'))
return hl.hexdigest()
request = http.Request("http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule")
request.headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN',
'Cache-Control': 'no-cache',
'Connection': 'Keep-Alive',
'Content-Length': '204',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': '[email protected]; OUTFOX_SEARCH_USER_ID_NCOO=500507281.7589852; JSESSIONID=aaaTgHrZGrr3BdPW8snsw; ___rl__test__cookies=' + str(
int(time.time() * 1000)) + '; fanyi-ad-id=46607; fanyi-ad-closed=1',
'Host': 'fanyi.youdao.com',
'Origin': 'http://fanyi.youdao.com',
'Referer': 'http://fanyi.youdao.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134',
'X-Requested-With': 'XMLHttpRequest'
}
data = {
'action': 'FY_BY_CLICKBUTTION',
'client': 'fanyideskweb',
'doctype': 'json',
'from': 'AUTO',
'i': 'want',
'keyfrom': 'fanyi.web',
'salt': str(int(time.time() * 1000)),
'smartresult': 'dict',
'to': 'AUTO',
'typoResult': 'false',
'version': '2.1'
}
data['sign'] = md5(data['client'] + data['i'] + data['salt'] + "ebSeFb%=XZ%T[KZ)c(sy!")
request.data = urllib.parse.urlencode(data).encode('utf-8')
response = http.urlopen(request)
print(response.read().decode('utf-8'))
运行结果:
{
"translateResult": [
[{
"tgt": "想要",
"src": "want"
}]
],
"errorCode": 0,
"type": "en2zh-CHS",
"smartResult": {
"entries": ["", "n. 需要;缺乏;贫困;必需品\r\n", "vt. 需要;希望;应该;缺少\r\n", "vi. 需要;缺少\r\n"],
"type": 1
}
}