赞
踩
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数据爬取的相关知识
我来要赞啦,如果觉得能学到什么,就点个赞再走吧,
欢迎各位路过的大佬评论指正
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。