每天30分钟 一起来学习爬虫——day3(urllib库——post请求 实例:抓取百度翻译)

post请求

GET 请求方法中,参数拼接在 url 中,而 post 请求方法中,表单数据(form data)参数单独传递,不拼接,而且,post 表单数据是 字节类型,不是 str 所以说要 encode 一下,下面我们以爬取百度翻译的结果为例讲解一下

爬取百度翻译的结果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
我们通过上面的图,分析一下,sug 是接口然后提交Formdata,就可以获取到要查的单词啦,下面看代码,注意看注释

# 输入 word 可以抓取想要查的单词的翻译
import urllib.request
import urllib.parse
import random
post_url = 'https://fanyi.baidu.com/sug'
word = input('请输入要查询的单词:')
# 构建 post 表单数据
form_data = {
    'kw': word,
}
# 处理表单数据
# POST data 应该是 bytes 而不是 str 所以我们把字典拼接,然后转化为 bytes 类型
form_data = urllib.parse.urlencode(form_data).encode()
# 伪装,在昨天已经初步讲解了一下如何伪装,
# 但是总是用同一个头也不好,所以我们找几个常用的头,每次随机用一个头
user_agent = [
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
    "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
    "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
    "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
    "Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
    "MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
    "Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10",
    "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
    "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+",
    "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
    "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)",
    "UCWEB7.0.2.37/28/999",
    "NOKIA5700/ UCWEB7.0.2.37/28/999",
    "Openwave/ UCWEB7.0.2.37/28/999",
    "Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999",
]
# 随机获取一个请求头 并构建请求对象
headers = {'User-Agent': random.choice(user_agent)}
request = urllib.request.Request(url=post_url, headers=headers)

#除了上面介绍的方法,我们还可以动态的添加 headers,
#request = urllib.request.Request(post_url)
#request.add_header('User-Agent',random.choice(user_agent))
#  发送请求
# GET 请求方法中,参数拼接字在 url中,而post 请求方法中,参数单独传递,不拼接
response = urllib.request.urlopen(request, data=form_data)

print(response.read().decode())
print(request.get_header("User-agent"))

打印出来的是 josn 文件,我们看不懂,但是,json在线解析可以解析出来。

在这里插入图片描述

还是爬取百度翻译的结果

我们再看刚才的XHR,除了sug,还有一个接口v2
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述这次呢,我们查一下单词baby
我们这次用一下fiddle (不知道的看看这个),学完还一直没用过
在这里插入图片描述
先像刚才一样爬一下,

import urllib.request
import urllib.parse
post_url = 'https://fanyi.baidu.com/v2transapi'
# 这个word是我们查的单词
word = 'baby'
# 构建处理表单数据,
form_data = {
    'from':'en',
    'to':'zh',
    'query': word,
    'transtype':'realtime',
    'simple_means_flag':'3',
    'sign':'814534.560887',
    'token':'c3ce1807e40e3ac6273b2ff29ff92dc4',
}
form_data = urllib.parse.urlencode(form_data).encode()
# 伪装头部,
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36',
 }
#构建请求
request = urllib.request.Request(url=post_url,headers=headers)
#发送请求
response = urllib.request.urlopen(request,data=form_data)
print(response.read().decode())

嘿嘿,我们发现,爬取失败了,这是为什么呢,注意了:如果出错,首先思考,没有完全模拟浏览器,,所以不允许访问。
我们把fiddle的头部信息全复制过来试试,当然有的不能要,注意看代码的注释
在这里插入图片描述

import urllib.request
import urllib.parse
post_url = 'https://fanyi.baidu.com/v2transapi'
# 这个word是我们查的单词
word = 'baby'
# 构建处理表单数据,
form_data = {
    'from':'en',
    'to':'zh',
    'query': word,
    'transtype':'realtime',
    'simple_means_flag':'3',
    'sign':'814534.560887',
    'token':'c3ce1807e40e3ac6273b2ff29ff92dc4',
}
form_data = urllib.parse.urlencode(form_data).encode()
# 伪装头部,
# 这里注意,全复制过来以后,有一个支持的压缩类型,这个不能要,因为 我们不会解压,而浏览器会自动解压
headers = {
    'Host': 'fanyi.baidu.com',
    # 'Connection': 'keep-alive',  不要这个好像也没问题,
    # 'Content-Length': '121',   这是内容长度,以后也可以不要,这个会限制我们收到的内容。
    # 'Accept': '*/*', 没有这个也没问题
    'Sec-Fetch-Dest': 'empty',
    'X-Requested-With': 'XMLHttpRequest',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36',
    # 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 这个也可以不用
    'Origin': 'https://fanyi.baidu.com',
    'Sec-Fetch-Site': 'same-origin',
    'Sec-Fetch-Mode': 'cors',
    'Referer': 'https://fanyi.baidu.com/',
    #'Accept-Encoding': 'gzip, deflate, br', 这个不能有会返回压缩的文件
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Cookie': 'BAIDUID=F8C9498274C03E146FAB92DE7C6C4C18:FG=1; BIDUPSID=F8C9498274C03E146FAB92DE7C6C4C18; PSTM=1573075543; BDUSS=Wx6dC1xdXpiWWpOflZsYzAxTjByWUExZ1JIZDlXUUNVMzE4b1l4eUpVZVV2UlplSUFBQUFBJCQAAAAAAAAAAAEAAABoEMZ~WV8xMTkyMTY3Mjc0vM4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJQw712UMO9dd; delPer=0; PSINO=1; BDRCVFR[M7pOaqtZgJR]=I67x6TjHwwYf0; BDRCVFR[J6KCWSEUjPm]=OjjlczwSj8nXy4Grjf8mvqV; H_PS_PSSID=30744_1459_21105_30616_26350_22158; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1581470885; to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; APPGUIDE_8_2_2=1; from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; yjs_js_security_passport=375a07328f6090f630c4e11cb1f65325b2da104d_1581471039_js; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1581472957',
}
#构建请求
request = urllib.request.Request(url=post_url,headers=headers)
#发送请求
response = urllib.request.urlopen(request,data=form_data)
print(response.read().decode())

哈哈,好像成功了的样子,把返回的写到 json在线解析 解析出来看看吧,如果解析错了,就在cmd里运行一下,可能编辑器把返回值给截断了。
我们换的单词再查一下看看,比如 bad 意外的是我们得到了一个{"errno":998,"from":"en","to":"zh","query":"bad"}
事实上,这个代码只能查 初始的 baby 这个一个单词,因为百度翻译都有 加密的措施 ,看formdata 里面的 sign token 就是加密的方式
也就是说 要根据 查的单词来 计算 sign(令牌) token(身份)



今天的post学习就到这了,明天学习Ajax数据爬取的相关知识

我来要赞啦,如果觉得能学到什么,就点个赞再走吧,
欢迎各位路过的大佬评论指正

发布了50 篇原创文章 · 获赞 50 · 访问量 2715

猜你喜欢

转载自blog.csdn.net/weixin_45691686/article/details/104925556