Python爬蟲中如何通過post發請求,瀏覽器控制檯抓包教程,有道翻譯爬蟲程序,通過python僞裝翻譯(post案例)

目錄

一、瀏覽器控制檯抓包

1.打開方式以及常用選項

2.控制檯NetWrok  

二、Python爬蟲中如何通過post發請求

1.Post請求

2.Python中使用post請求

三、有道翻譯爬蟲程序,通過python僞裝翻譯(post案例)

1.需求分析

2.post請求分析

3.js方法轉python方法

4.程序設計


一、瀏覽器控制檯抓包

在很多的工作中都是需要進行抓取到網絡的相關數據進行分析,來進行查看訪問到服務器返回的數據是否正確,來判斷是否是自己想要的數據,可以通過這些數據做相關內容測試,和二次開發,常用的接口測試方法。

1.打開方式以及常用選項

打開瀏覽器,按F12打開控制檯或者右鍵點擊檢查。控制檯界面如下,右側即爲控制檯。控制檯有數個選項,我們依次來說。

Elements:查看元素節點位置,看到Elements左側的鼠標按鈕(或者Ctrl+shift+c),選中後點擊網頁文件的任意位置,Elements欄會顯示鼠標停留地方的Elements節點屬性。

Console:控制檯,交互模式,可以對JavaScript代碼進行測試。

Sources:格式化輸出並可以打斷點調試JS代碼,助於分析爬蟲中一些參數。

Performance:主要用於做前端性能優化,可以監控到毫秒級別,網絡,cpu等性能在數據收發時的狀態。

 

 

2.控制檯NetWrok  

NetWrok的作用是查看被抓取網絡數據包,也可以檢查cookies,Headers請求頭等信息。下圖是Network工作圖以及一些被抓取到的網絡文件。

ALL:抓取所有的網絡數據包

XHR:抓取異步加載的網絡數據包,如Ajax文件

JS:抓取所有的JS文件

CSS:抓取樣式文件

Img/Media:抓取圖片,視頻

下圖是cookies的信息,比如我們賬號密碼也包含在裏面:

 

二、Python爬蟲中如何通過post發請求

1.Post請求

我們在使用Python做爬蟲的時候,通常使用的是requests模式的get()方法,這裏介紹Post方法。做過前端的應該知道,前端頁面要提交請求有post和get方法,post可以隱藏參數,也可以對傳輸內容加密,一般在表單(from)數據中,我們進行登錄也是用的表單提交,還有各種網站的註冊信息也是。在網頁中,除了我們通過url訪問網頁時用get方法外,只要你用得着提交數據的,絕大多是都是用的post請求。

2.Python中使用post請求

在python中用post請求很容易,需用用到requests模塊,與get方法不同的是,post方法需要傳入data方法,data在這裏是一個字典,用於裝提交的參數信息。

rep=requests.post(url,data,headers) 

 

三、有道翻譯爬蟲程序,通過python僞裝翻譯(post案例)

1.需求分析

打開有道翻譯首頁,url:http://fanyi.youdao.com/ 

我們要做的就是用python提交請求翻譯的內容,然後由python接受,其實就相當於用電腦來模擬人的操作,有什麼用呢,主要有兩點:

1)適合大批量翻譯:對於較多的翻譯內容,用機器來請求比人手動點擊要效率高的多

2)作爲第三方插件:當你在設計自己的程序代碼時,如果要用到翻譯的功能,你可以自己寫一個翻譯程序,其難度可想而知,也可以寫一套爬蟲程序,將某個第三方的爬蟲程序作爲你程序的一部分,非常節省時間。

我們下面要做的就是寫一段python爬蟲程序,來提交翻譯請求。如果用get肯定是不行的,get將參數與url一起發給接收方。但是有道明顯不是這麼做的,在發請求前後url沒有發生變化,說明他是通過post發送的請求。如圖所示。

 

總結:按照需求,我們要用python來發送請求和接受結果,以此實現翻譯功能,本程序的核心在與如何生成post請求表達(form),下面進一步分析。

 

2.post請求分析

我們的目的旨在分析在發送post請求時,瀏覽器到底封裝了什麼數據(表單數據),也就是data中究竟要裝什麼,才能僞裝成瀏覽器向服務器端發送請求。下面我們來翻譯進行一次翻譯,如圖,翻譯後,進入控制檯界面,點擊網絡,在XHR中找到了請求表達,也就是說有道翻譯是基於AJAX+JS發送請求的,查看此Ajax文件,我們看到了他的請求頭:

 

下面我們一個個來分析請求頭中的內容,以下是全部內容,是我對每個文本的解釋,可能並不準確:

i很好理解,就是我們請求的對象(翻譯對象),from誰發起的,to發給誰,smartresult直接返回,client客戶端類型(這裏是web瀏覽器),salt/ts/bv不詳,doctype爲json數據類型,版本2.1,keyfrom應該是key來自誰(這裏是web瀏覽器),action動作立即執行。

i:我是一匹狼

from:AUTO

to:AUTO

smartresult:dict

client:fanyideskweb

salt:15818489372401

sign:7c2431437f3312132086089fcbad13d0

ts:1581848937240

bv:bc250de095a39eeec212da07435b6924

doctype:json

version:2.1

keyfrom:fanyi.web

action:FY_BY_REALTlME

 也就是說,我們只需要把這些東西丟到post請求的data中去,就可以模擬瀏覽器進行請求,但是問題來了,這些內容哪些是變化的哪些是不變的?當然第一個變化的肯定是i屬性,也就是我們請求翻譯的對象,我們還需要找到其他變化的屬性。我們再啓動一個瀏覽器,打開有道翻譯,我這裏是打開的火狐瀏覽器,並且進行了一次請求,如下圖。

我們通過對比兩組表單數據來找出不同的地方,經過分析,我找出了4個會變化的屬性(i可以忽略,實際只有3個)。接下來我們要分析這些屬性爲什麼會變化。

谷歌:

i:我是一匹狼

salt:15818489372401

sign:7c2431437f3312132086089fcbad13d0

ts:1581848937240

火狐:

i:滄海桑田

salt:15818489372401

sign:7c2431437f3312132086089fcbad13d0

ts:1581848937240

 到目前爲止,我們知道這些表單數據是Ajax+js來進行請求的,所以要分析這些屬性爲什麼會變化,就要去js文件中查看代碼,看看其js文件怎麼寫的,要找到這些屬性出現在哪個js文件中,我們按ctrl+f彈出搜索框,在窗口輸入salt:,果然有一個結果,點擊此js文件進入代碼區。

 點擊後,在Response處會顯示出代碼,但是格式比較亂,點擊我圖中劃線的那個{},系統會自動編排格式。把鼠標停留在代碼區裏,按ctrl+shift+f,彈出搜索框,搜索salt:

 

一共看到四個結果,第一個結果是對屬性的封裝,不是我們要找的,看到第二個結果,這就是我們想看的了。 

 第二個結果很明顯的寫出了ts,bv,salt,sign是的數據是如何產生的,我們現在一個個進行分析:

 

1)ts

ts很好理解,js代碼顯示爲當前時間:"" + (new Date).getTime(),並且還將這個時間轉換爲了字符串。是一個13位的字符串.

2)salt

r + parseInt(10 * Math.random(), 10);這個也很好理解,就是把前的bv加上一個0-10的隨機數。

3)sign

n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")。使用md5進行加密,"fanyideskweb"一串字符串,爲固定格式,e目前不知道是什麼,i就是salt,再加上"n%A-rKaT5fb[Gy?;N5@Tj"一段固定字符串。

我們進一步分析這個e是什麼,在8373行加上斷點(斷點調試),在翻譯框中重新輸入一段文字,可以看到這個e到底是什麼,原來就是我們要翻譯的內容,現在我們知道e是什麼了,所有的分析已經over。

 

總結:

1.ts:"" + (new Date).getTime()

2.salt:r + parseInt(10 * Math.random(), 10);

3.sign:n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj"),e是翻譯內容

 

3.js方法轉python方法

我們現在要做的就是把js方法轉換爲python方法,讓python能夠輸出同樣的結果。

1)ts:"" + (new Date).getTime()

python中調用時間的模塊是time,與js不同的是python只生成10位,而js生成13位,所以要給python的time方法在乘以1000,最好將它轉換成字符串即可,如下:

import time
ts=str(int(time.time()*1000))

2)salt:r + parseInt(10 * Math.random(), 10);

這個好寫,r是ts,也就是ts加一個0-9的隨機數(js方法上的10代表10以內),python代碼爲

import random
import time 
ts=str(int(time.time()*1000))
salt=ts+str(random.randint(0,9))

3)sign:n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")

import hashlib
sign="fanyideskweb"+e+salt+str(hashlib.md5("123".encode()).hexdigest())+"n%A-rKaT5fb[Gy?;N5@Tj")

 

4.程序設計

本程序一共4個函數:

1.__init__():初始化參數,重點在於包裝請求頭,有代理的可以寫上代理,我沒有代理所以不寫

2.make_Data():用戶封裝data,關鍵在於三個變動參數的生成

3.translate():用於請求翻譯並取得結果

4.run():函數執行入口

import time
import random
import hashlib
import requests

class YoudaoTranslate(object):

    #初始化參數
    def __init__(self):
        #請求的url
        self.url="http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
        #封裝請求頭,要求和網易請求一致
        self.headers={
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Accept-Encoding": "gzip, deflate",
            "Accept-Language": "zh-CN,zh;q=0.9",
            "Connection": "keep-alive",
            "Content-Length": "278",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Cookie": "[email protected]; JSESSIONID=aaaLYHK5MHJzKbVCpznbx; OUTFOX_SEARCH_USER_ID_NCOO=2145091673.4136953; ___rl__test__cookies=1581848937227",
            "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/78.0.3904.108 Safari/537.36",
            "X-Requested-With": "XMLHttpRequest",
        }
        # 如果有代理可以寫代理
        # self.proxies={
        #     'http':'http://',
        #     'https':'https://'
        # }

    #該函數用於封裝data
    def make_Data(self,text):
        e=text
        ts=str(int(time.time()*1000))
        salt=ts+str(random.randint(0,9))
        string="fanyideskweb"+e+salt+"n%A-rKaT5fb[Gy?;N5@Tj"
        sign=hashlib.md5(string.encode()).hexdigest()
        return ts,salt,sign

    #該函數用於請求翻譯結果
    def translate(self,text):
        ts,salt,sign=self.make_Data(text)
        #定義data,替換ts,salt,sing的值
        data = {
            'i': text,
            'from': 'AUTO',
            'to': 'AUTO',
            'smartresult': 'dict',
            'client': 'fanyideskweb',
            'salt': salt,
            'sign': sign,
            'ts': ts,
            'bv': 'bc250de095a39eeec212da07435b6924',
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'FY_BY_REALTlME',
        }
        #用post做請求,獲得json輸出,便於我們提取數據
        #請求結果格式爲:{"translateResult":[[{"tgt":"Who are you","src":"你是誰"}]],"errorCode":0,"type":"zh-CHS2en","smartResult":{"entries":["","Who are you\r\n"],"type":1}}
        rep=requests.post(url=self.url,data=data,headers=self.headers).json()
        result=rep["translateResult"][0][0]["tgt"]
        return result

   #入口函數
    def run(self):
        text=input("輸入被翻譯內容:")
        result=self.translate(text)
        print("翻譯結果爲:",result)

if __name__=="__main__":
    translate=YoudaoTranslate()
    translate.run()

執行效果: 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章