Python クローラーは歴史的な安値をゆっくりと購入して、JS のリバース エントリをクロールします

[この記事は学習のみを目的としています。違法な目的には使用しないでください。違法な使用については責任を負いません]

序文:

最近Javaからクローラーに乗り換える予定なのですが、休日に何もすることがないときに何かしたいので、ゆっくり買った商品の過去の価格を下げることができないかなぁと考えています。(追記: 著者は通常、ショッピングの際に過去の価格を表示するために Slow Buy を使用するのが好きですが、アプリを使用しています :-)

文章

まず、Google ブラウザを使用してゆっくり購入 Web ページ (F12) を開き、任意の製品をクリックしてインターフェイスを確認します。必要なここに画像の説明を挿入
価格を見つけて、パラメーターを確認します。
ここに画像の説明を挿入
リクエスト ヘッダー:
ここに画像の説明を挿入

うーん、パラメーターは非常に単純で、不明な cxid は 1 つだけなので、Web サイト http://cu.manmanbuy.com/discuxiao_4076382.aspx を調べてみました。えっと、パラメータは完了しましたか?すぐに Pycharm を開いて次のコードを書きました。

import requests
resp = requests.get('http://tool.manmanbuy.com/history.aspx?DA=1&action=gethistory&url=&bjid=&spbh=&cxid=4076382&zkid=&w=310&token=')
print(resp.text)

出力:

{"datePrice":"[1602518400000,20.90,\"\"],[1602604800000,20.90,\"\"],[1602691200000,20.90,\"\"],[1602777600000,20.90,\"\"],[1602864000000,20.90,\"\"],[1602950400000,20.90,\"\"],[1603036800000,20.90,\"\"],[1603123200000,20.90,\"\"],[1603209600000,20.90,\"\"],[1603296000000,20.90,\"\"],[1603382400000,20.90,\"\"],[1603468800000,20.90,\"\"],[1603555200000,20.90,\"\"],[1603641600000,20.90,\"\"],[1603728000000,20.90,\"\"],[1603814400000,20.90,\"\"],[1603900800000,17.9000,\"\"],[1603987200000,17.90,\"\"],[1604073600000,17.90,\"\"],[1604160000000,17.90,\"\"],[1604246400000,17.90,\"\"],[1604332800000,17.90,\"\"],[1604419200000,17.90,\"\"],[1604505600000,17.90,\"\"],[1604592000000,17.90,\"\"],[1604678400000,17.90,\"\"],[1604764800000,17.90,\"\"],[1604851200000,17.90,\"\"],[1604937600000,17.90,\"\"],[1605024000000,17.90,\"\"],[1605110400000,17.90,\"\"],[1605196800000,17.90,\"\"],[1605283200000,17.90,\"\"],[1605369600000,17.90,\"\"],[1605456000000,17.90,\"\"],[1605542400000,17.90,\"\"],[1605628800000,17.90,\"\"],[1605715200000,17.90,\"\"],[1605801600000,17.90,\"\"],[1605888000000,17.90,\"\"],[1605974400000,17.90,\"\"],[1606060800000,17.90,\"\"],[1606147200000,17.90,\"\"],[1606233600000,17.90,\"\"],[1606320000000,17.90,\"\"],[1606406400000,17.90,\"\"],[1606492800000,17.90,\"\"],[1606579200000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1606665600000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1606752000000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1606838400000,15.36,\"购买5件,当前价:16.80,满减:满3件,打9.5折,优惠券:满69减3\"],[1606924800000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607011200000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607097600000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607184000000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607270400000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607356800000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607443200000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607529600000,16.8,\"京东秒杀价:16.8\"],[1607616000000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607702400000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607788800000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607875200000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1607961600000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608048000000,16.40,\"购买4件,当前价:17.90,满减:满49减3,优惠券:满69减3\"],[1608134400000,16.40,\"购买4件,当前价:17.90,满减:满49减3,优惠券:满69减3\"],[1608220800000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608307200000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608393600000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608480000000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608566400000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608652800000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608739200000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608825600000,10.90,\"购买1件,当前价:17.90,优惠券:满17减7\"],[1608912000000,15.60,\"购买5件,plus价格16.8,满减:满49减3,优惠券:满69减3\"],[1608998400000,15.60,\"购买5件,plus价格16.8,满减:满49减3,优惠券:满69减3\"],[1609084800000,15.60,\"购买5件,plus价格16.8,满减:满49减3,优惠券:满69减3\"],[1609171200000,16.40,\"购买4件,当前价:17.90,满减:满49减3,优惠券:满69减3\"],[1609257600000,16.40,\"购买4件,当前价:17.90,满减:满49减3,优惠券:满69减3\"],[1609344000000,16.40,\"购买4件,当前价:17.90,满减:满49减3,优惠券:满69减3\"],[1609430400000,17.90,\"\"],[1609516800000,17.90,\"\"],[1609603200000,17.90,\"\"],[1609689600000,16.40,\"购买4件,当前价:17.90,满减:满49减3,优惠券:满69减3\"],[1609776000000,16.40,\"购买4件,当前价:17.90,满减:满49减3,优惠券:满69减3\"],[1609862400000,16.40,\"购买4件,当前价:17.90,满减:满49减3,优惠券:满69减3\"],
...

コンテンツが長すぎるため、取得時に多くが省略されていますが、ページ上の情報を比較すると、返された dataPrice フィールドの最初のリストが日付とタイムスタンプ、2 番目が価格、 3 番目は完全割引情報です

これが降りてきたと思った?そこで、検索して実験する製品をさらにいくつか見つけました。
ここに画像の説明を挿入
これは JD 製品パラメータです。emmm は cxid を bjid に置き換えるようです? そこで、先ほどのコードテストに bjid パラメータを戻してみたところ、正常に実行できることがわかり、bjid が取得できるかどうかページを確認したところ、えっと
ここに画像の説明を挿入
取得できました、問題ありません。しかし、最初の 2 つの bjid が 0 であるのは一体どういうことでしょうか? bjid 0 の 2 つの製品を続けて確認しましたここに画像の説明を挿入
が、ロードできませんでした。ジャンプして見るここに画像の説明を挿入

そのようなページがありますが、通話のインターフェイスは同じではありませんか?WF?このような操作がまだあるのでパラメータをもう一度見てみると、ここに画像の説明を挿入
トークンが余分にありました。うーん、この TM は不正です。フロントエンド JS によって生成される必要があるとは考えないでください。JS のデバッグはゆっくりと始めるしかありません。

まず、F12 の左側にある CTRL+F を押して検索ボックスを開き、トークンを検索します (結局のところ、これはトークン パラメーターです。この文字列は js には存在しませんよね?)。観察すると
ここに画像の説明を挿入
、次のトークンはすべて URL 内にあります。トークンをトークンに渡す前に、まずトークンを取得する必要があるため、それを見る必要はなく、主に最初のいくつかの js ファイルを参照します。絶え間なく観察した結果、ついにトークンがcutomRequest.jsファイルにあることがわかりました。なぜでしょうか? 下の図を見てください:
ここに画像の説明を挿入
トークンに値を割り当てる操作があり、よく見ると ajaxPost 操作もあります。次の質問を見るため、ここではスクリーンショットを撮りません。 「ソース」をクリックしてソース コードを入力します (上記のインターフェイスを確認してください)。タブはネットワークであり、ソースは通常、ネットワークの左側にあります。) 前のネットワーク図から、次のことができますここに画像の説明を挿入
。 CutomRequest.js ファイルがtool.manmanbuy.com/Scripts ディレクトリにあることがわかります。見ませんでしたか?次に、スクリーンショットをお見せします。
ここに画像の説明を挿入
この時点で、ソースの下にあるファイルを開きます (Google ブラウザーがソース ファイルを開き、きれいに印刷されたプロンプトが表示されます。確認してください。これはフォーマットされた JS コードです。そうでない場合は、メガネが見えなくなる(表示されない)、先ほどのトークンの位置にブレークポイントを置き、えっ?ブレークポイントがヒットしないのですか?下の図を見てください。
ここに画像の説明を挿入
色が青に変わったら、ブレークポイントが設定されています。このとき、デバッグするためにページを更新すると、データ情報が表示されます。
ここに画像の説明を挿入
パラメータをよく見てください、WF? これらの変数は一体何なのでしょうか? これは JS の混乱の幽霊に違いないので、見ないでください。このメソッドの最初の行からデバッグを開始するので (結局のところ、トークンがどのように生成されるかを知るには入力パラメーターを知る必要があります)、えっと、メソッドと製品リンクを取得して
ここに画像の説明を挿入
、デバッグに進みます。ナニ?デバッグ方法が分からないのですか?ジャンプ先の行にブレークポイントを設定し、右上隅にある青い右矢印をクリックします。最初の手順は変数を定義することですが、心配する必要はありません。一番下にジャンプして t パラメーターを設定します。
ここに画像の説明を挿入
上の図に示すように、マウスを選択してしばらくホバーすると、ブロック操作全体の結果が表示されます。うーん、私の JS はあまり良くありませんが、一般的な意味は、最初に Date オブジェクトを作成してから呼び出します。 valueOf メソッド、次の行に進みます。えっと、ここに画像の説明を挿入
上記のデバッグ情報を参照してください。この行では、現在の瞬間のミリ秒レベルのタイムスタンプが生成されます。タイムスタンプ分析プラットフォームと比較できますが、ここでは比較しません。上記のデバッグからわかるように、受信データは最初に t パラメーターを使用して現在のタイムスタンプに保存され、次に下に進みます。foreach は
ここに画像の説明を挿入
ループである必要があり、データのキーは上記で示されており、ソートされています (小さい文字から小さい文字まで) 大、ここではスクリーンショットを撮りません)、ここにトラバーサル キーがあるはずです。下に進みます。
ここに画像の説明を挿入
メソッド トラバーサルの場合は、f 行をクリックしてジャンプします。このループ全体のロジックはおそらく次のとおりです。前のパラメータを入力します。 json オブジェクトが新しい json オブジェクトにコピーされます。興味のある友達はデバッグに行って、自分で試してみることができます。ここではスペースを消費しません。それでは続行します: WF
ここに画像の説明を挿入
? 秘密とは何ですか?ここでは、クイック検出メソッドを直接使用して、シークレットが修正されているかどうかを検出します。何?検出方法は? ページを数回更新し、デバッグがここに来るのを待って値が同じかどうかを比較し、同じであれば高確率は固定値です。ここではシークレットが修正されていることを確認したので、そのまま書いて、次のサイクルを見てデバッグするだけですが、両者は等しくないと判断され、どちらも成立しているので、直接見てみましょう。ロジックは問題ありません:
ここに画像の説明を挿入
これは再びネストされた関数であり、デバッグはそれが合計関数であること、つまり 2 つのパラメーターの合計であることを確認するためにジャンプし、次に 2 つのパラメーターを調べます: 呼び出し元の関数が合計関数の中にネストされているここに画像の説明を挿入
、この壊れた関数は、xxx(a, b) を関数呼び出しにするものであるため、各パラメーターと 2 番目のパラメーターは encodeURIComponent によって呼び出され、次に 2 つのパラメーターが何であるかを確認します。
ここに画像の説明を挿入
最初のパラメータがキーであり、2 番目のパラメータである this のリンクであることがわかります。jsonのキーと値だけではないでしょうか?それでは、このサイクルのロジックは、キーと値を urlencode してからそれらを結合することになるのでしょうか? 下を見続けます:
ここに画像の説明を挿入
案の定、この行には += シークレットがあるため、最後にシークレットがあります。前の部分は分析と一致しています。下に進み続けます: えっと、大文字を 1 回だけ大文字にするには、下に進みます
ここに画像の説明を挿入
:ここに画像の説明を挿入
えっと, hex_md5 が md5 であることは誰もが推測できるはずです。md5 が完了したら、トークンの生成が完了するように、もう一度大文字にする必要があります。ここでは、コード全体のロジックを記述します。

import time
from urllib.parse import quote
import hashlib


def parse_req(d):
    # 设置当前时间ms
    d['t'] = int(time.time() * 1000)
    # 拷贝对象
    n = copy.deepcopy(d)
    # 提取key
    ks = list(n.keys())
    # key排序
    ks.sort()
    # secret
    ask = 'c5c3f201a8e8fc634d37a766a0299218'
    # token先拼一个secret
    mask = ask
    # 循环key
    for k in ks:
        # token拼接key和value urlencode后的结果
        # 这里说一下key都是英文,urlencode后没有什么变化的,所以就省略了
        # 还有一点urllib的quote库不会把/转为%2F, 所以这里自己转了下,大家有什么好用只对参数进行urlencode的包可以分享一下
        mask += f'{
      
      k}{
      
      quote(str(n[k])).replace("/", "%2F")}'
    # token最后再拼一个secret
    mask += ask
    # token转大写
    mask = mask.upper()
    # md5 编码
    md5 = hashlib.md5()
    md5.update(mask.encode('utf-8'))
    # 获取md5编码后的结果再转一次大写就是token的值
    d['token'] = md5.hexdigest().upper()
    # 最后把含t和token的参数返回
    return d

この時点で、トークン取得プロセス全体が完了したので、興奮してすぐにテストするコードを書きました。

# parse_req上面写了这里就不写了
req = parse_req({
    
    'key': 'https://detail.tmall.com/item.htm?id=638265162028', 'method': 'getHistoryTrend'})
headers = {
    
    
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'ASP.NET_SessionId=k55tyozvlmbcmbiwm1yn0ng1; Hm_lvt_85f48cee3e51cd48eaba80781b243db3=1641120605; Hm_lvt_01a310dc95b71311522403c3237671ae=1641120605; _ga=GA1.2.1386971910.1641120645; _gid=GA1.2.1891960103.1641120645; Hm_lpvt_85f48cee3e51cd48eaba80781b243db3=1641186149; Hm_lpvt_01a310dc95b71311522403c3237671ae=1641186149',
    'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': 'Windows',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Site': 'same-origin',
    'Accept-Encoding': 'gzip, deflate, br',
    'Sec-Fetch-User': '?1',
    'Connection': 'keep-alive',
    'Host': 'tool.manmanbuy.com',
    'Origin': 'https://tool.manmanbuy.com',
    'Referer': 'https://tool.manmanbuy.com/HistoryLowest.aspx?url=https%3a%2f%2fitem.jd.com%2f100011493273.html',
}
print(headers)
print(req)
resp = requests.post(f'http://tool.manmanbuy.com/api.ashx', data=req, headers=headers)
print(resp.status_code)
print(resp.text)

これを返してくれるとは思わなかった

{"msg":"无效的票据","code":1,"data":null,"count":0}

何?隠しパラメータはあるのでしょうか?リクエスト ヘッダーをもう一度確認したところ、Authorization パラメータがあることがわかりました
ここに画像の説明を挿入
。えっと、それはそんなに難しいですか? 仕方がないので勉強し続けるしかないのですが、先ほどのcustomRequestに戻ってみると、ajaxPostメソッドがあり、ここからロジック呼び出し全体が入っていることがわかります。ナニ?ここからどうやってわかるのですか?と尋ねます。ajaxGet などをデバッグしましたが、プロセスはそこに到達するまで停止しません。そこで、ajaxPost のブロック全体の処理ロジックを確認する必要があります。ここに画像の説明を挿入
これがフロントエンド ajax を呼び出すメソッドであることがわかります。内部を見てみましょう。リクエスト ヘッダーを設定する方法は絶対にありません。 URL、タイプ、およびデータなので、予期せぬことはありません。これは beforeSend にあります (データのパラメータ値は getParam メソッドが呼び出され、これが t とトークンを取得したばかりのメソッドであることを補足します。興味のある友人は次のようにしてデバッグできます) beforeSenc メソッドでは、最初に「ここに画像の説明を挿入
オブジェクトについては心配しないで、if にデバッグしてください。デバッグ後に if 条件は true でなければなりません。そのため、内部のロジックを確認するだけです (次のステップはこの記事の焦点)
ここに画像の説明を挿入
まず、最初の変数が setRequestHeader 関数であることに注目してください。興味深いですね。次へ進みますここに画像の説明を挿入
。これは必要なパラメータではないでしょうか? TATするのは簡単ではありません。背後にある価値を見つめ続けてくださいここに画像の説明を挿入

過去にジャンプするローカル関数は合計関数です (個人的に関数 (a,b) return a+b を呼び出すために使用されます。この関数は合計関数と呼ばれます。実際には、文字列の結合、上記のトークンである可能性があります)同じです)、「後:
ここに画像の説明を挿入
BasicAuth」に進み、最初に BasicAuth の文字列とスペースを追加することを説明し、下に進みます:
ここに画像の説明を挿入
getTicket() メソッドを詳しく説明します。えっと、このメソッドを見てみましょう:
ここに画像の説明を挿入
最初の定義オブジェクトは同じです。見ないでください。ここでローカル関数の関数参照が呼び出されます。これはおおよそ次のようになります (function(a,b) return a(b)) 一体、$reference #ticket
ここに画像の説明を挿入
? 幸いなことに、私は jquery について少し知っています。jquery では $() が dom を直接参照できることは知っています。そうでなければ、それは素晴らしいでしょう。その場合、ここでのロジックは $("#ticket") となり、val を確認する必要があります。方法ここに画像の説明を挿入
? $("#ticket").val()? になると推定されます。jqueryを書くのは久しぶりなのでこんな風に書いているのか分かりませんが、おそらくページIDの値をチケットとして取得するということなのでしょうか?何?まだこのままプレイできますか?デバッグせずにこれを知ることができる人はいないし、混乱していてまったく検索できません。私の心の中には「素晴らしい」という言葉しかありません。チケットを検索するページに移動しましょう:
ここに画像の説明を挿入
いいですね、ここにこっそり手を埋めておきました。先ほどの js の後のロジックを続けて見てみましょう。チケットの後、ページを 1 回調整して次の情報を取得できます。
ここに画像の説明を挿入
if 条件は常に true であり、常に 176 > 4? と判断されます。これはナンセンスではありませんか。if 内のロジックは自分でデバッグできます。それをノックできない場合は、ロジックについて直接話しましょう。substr と substring を調整します。コア ロジックは、チケットから取得することです。 . 176番から4本の弦を取り出して前に置き、1番目から172番目までを後ろに置きます。? ? ? その時、私は黒い疑問符を思い出しました。なぜそのようなロジックがそれほど複雑に混乱するのでしょうか?Python を使って説明すると、ticket[:176][-4:] + ticket[:172]、脳の痛みです。したがって、Authパラメータの値はおそらくBasicAuth xxxxxxxxxxxxであるため、それを変更して次のコードを書きました

import copy
import requests

import time
from urllib.parse import quote
import hashlib


def parse_req(d):
    """
    这是解析请求啊,增加t和token参数
    """
    d['t'] = int(time.time() * 1000)
    n = copy.deepcopy(d)
    ks = list(n.keys())
    ks.sort()
    ask = 'c5c3f201a8e8fc634d37a766a0299218'
    mask = ask
    for k in ks:
        mask += f'{
      
      k}{
      
      quote(str(n[k])).replace("/", "%2F")}'
    mask += ask
    mask = mask.upper()
    md5 = hashlib.md5()
    md5.update(mask.encode('utf-8'))
    d['token'] = md5.hexdigest().upper()
    return d

def parse_basic_auth(ticket):
    """
    这是解析ticket的值啊,就是上面说的那逻辑
    """
    return ticket[:176][-4:] + ticket[:172]

# 请求头从network里面先都copy过来吧,不知道服务器会校验哪些头
headers = {
    
    
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'ASP.NET_SessionId=k55tyozvlmbcmbiwm1yn0ng1; Hm_lvt_01a310dc95b71311522403c3237671ae=1641120605; _ga=GA1.2.1386971910.1641120645; _gid=GA1.2.1891960103.1641120645; Hm_lvt_85f48cee3e51cd48eaba80781b243db3=1641120605,1641210384; sheng=广东; app-activity-download-close2=1; Hm_lpvt_85f48cee3e51cd48eaba80781b243db3=1641215142; Hm_lpvt_01a310dc95b71311522403c3237671ae=1641215142',
    'Upgrade-Insecure-Requests': "1",
    'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': 'Windows',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Site': 'same-origin',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Sec-Fetch-User': '?1',
    'Connection': 'keep-alive',
    'Host': 'tool.manmanbuy.com',
    'Referer': 'https://tool.manmanbuy.com/ValidateAlibaba.aspx'
}
# 先调取页面获取ticket值,之前js里面读的就是页面的input标签的值啊,所以咱要先调一次页面搞到ticket的值
resp = requests.get('http://tool.manmanbuy.com/HistoryLowest.aspx?url=https://item.jd.com/100011493273.html', headers=headers)

from bs4 import BeautifulSoup

b = BeautifulSoup(resp.text, 'html.parser')
ticket = b.select('#ticket')[0]['value']
print(ticket)

# 测试请求参数
req = parse_req({
    
    'key': 'https://detail.tmall.com/item.htm?id=638265162028', 'method': 'getHistoryTrend'})

# 通过ticket构建auth
auth = parse_basic_auth(ticket)

# 这是调用api.ashx接口的请求头,能扣过来也都扣过来,免得检车不通过
headers = {
    
    
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'ASP.NET_SessionId=k55tyozvlmbcmbiwm1yn0ng1; Hm_lvt_01a310dc95b71311522403c3237671ae=1641120605; _ga=GA1.2.1386971910.1641120645; _gid=GA1.2.1891960103.1641120645; Hm_lvt_85f48cee3e51cd48eaba80781b243db3=1641120605,1641210384; sheng=广东; app-activity-download-close2=1; _gat_gtag_UA_145348783_1=1; Hm_lpvt_85f48cee3e51cd48eaba80781b243db3=1641216852; Hm_lpvt_01a310dc95b71311522403c3237671ae=1641216852',
    'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': 'Windows',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Site': 'same-origin',
    'Accept-Encoding': 'gzip, deflate, br',
    'Sec-Fetch-User': '?1',
    'Connection': 'keep-alive',
    'Host': 'tool.manmanbuy.com',
    'Origin': 'https://tool.manmanbuy.com',
    'Referer': 'https://tool.manmanbuy.com/HistoryLowest.aspx?url=https%3a%2f%2fitem.jd.com%2f100011493273.html',
    'X-Requested-With': 'XMLHttpRequest', 
    # 这个就是咱要加上的参数
    'Authorization': 'BasicAuth ' + auth,
}
print(headers)
print(req)
# 调用api获取历史价结果
resp = requests.post(f'http://tool.manmanbuy.com/api.ashx', data=req, headers=headers)
print(resp.status_code)
print(resp.text)

これで、呼び出しインターフェイスは最終的に通常の結果を取得できるようになりました

{
    
    "msg":"","code":0,"data":{
    
    "haveTrend":1,"changPriceRemark":"降幅4%","runtime":59,"zouShi_test":2,"changePriceCount":32,"spbh":"10|638265162028","spUrl":"https://item.taobao.com/item.htm?id=638265162028","spPic":"https://img.alicdn.com/bao/uploaded/i3/260808543/O1CN01wH0pMP2CykFkX6kO5_!!0-item_pic.jpg","currentPrice":133.0,"spName":"口红礼盒套装大牌正品全套盒化妆国风雕花小众彩妆生日礼物送女友","lowerDate":"2021-06-06T00:00:00","lowerPrice":116.33,"bjid":464502722,"zouShi":1,"siteId":10,"siteName":"天猫商城","datePrice":"[1613664000000,188.00,\"\"],[1613750400000,188.00,\"\"],[1613836800000,188.00,\"\"],[1613923200000,188.00,\"\"],[1614009600000,188.00,\"\"],[1614096000000,188.00,\"\"],[1614182400000,188.00,\"\"],[1614268800000,188.00,\"\"],[1614355200000,188.00,\"\"],[1614441600000,188.00,\"\"],[1614528000000,188.00,\"\"],[1614614400000,188.00,\"\"],[1614700800000,188.00,\"\"],[1614787200000,188.00,\"\"],[1614873600000,188.00,\"\"],[1614960000000,188.00,\"\"],[1615046400000,188.00,\"\"],[1615132800000,188.00,\"\"],[1615219200000,188.00,\"\"],[1615305600000,188.00,\"\"],[1615392000000,188.00,\"\"],[1615478400000,188.00,\"\"],[1615564800000,188.00,\"\"],[1615651200000,188.00,\"\"],[1615737600000,188.00,\"\"],[1615824000000,188.00,\"\"],[1615910400000,188.00,\"\"],[1615996800000,188.00,\"\"],[1616083200000,188.00,\"\"],[1616169600000,188.00,\"\"],[1616256000000,188.00,\"\"],[1616342400000,188.00,\"\"],[1616428800000,138.00,\"\"],[1616515200000,138.00,\"\"],[1616601600000,138.00,\"\"],[1616688000000,138.00,\"\"],[1616774400000,158.00,\"\"],[1616860800000,158.00,\"\"],[1616947200000,158.00,\"\"],[1617033600000,158.00,\"\"],[1617120000000,158.00,\"\"],[1617206400000,158.00,\"\"],[1617292800000,158.00,\"\"],[1617379200000,158.00,\"\"],[1617465600000,158.00,\"\"],[1617552000000,158.00,\"\"],[1617638400000,158.00,\"\"],[1617724800000,158.00,\"\"],[1617811200000,158.00,\"\"],[1617897600000,158.00,\"\"],[1617984000000,158.00,\"\"],[1618070400000,158.00,\"\"],[1618156800000,158.00,\"\"],[1618243200000,158.00,\"\"],[1618329600000,158.00,\"\"],[1618416000000,158.00,\"\"],[1618502400000,158.00,\"\"],[1618588800000,158.00,\"\"],[1618675200000,158.00,\"\"],[1618761600000,158.00,\"\"],[1618848000000,158.00,\"\"],[1618934400000,158.00,\"\"],[1619020800000,158.00,\"\"],[1619107200000,158.00,\"\"],[1619193600000,138.0000,\"\"],[1619280000000,138.00,\"\"],[1619366400000,138.00,\"\"],[1619452800000,138.00,\"\"],[1619539200000,138.00,\"\"],[1619625600000,138.00,\"\"],[1619712000000,138.00,\"\"],[1619798400000,138.00,\"\"],[1619884800000,138.00,\"\"],[1619971200000,138.00,\"\"],[1620057600000,138.00,\"\"],[1620144000000,138.00,\"\"],[1620230400000,138.00,\"\"],[1620316800000,138.00,\"\"],[1620403200000,138.00,\"\"],[1620489600000,138.00,\"\"],[1620576000000,138.00,\"\"],[1620662400000,138.00,\"\"],[1620748800000,138.00,\"\"],[1620835200000,138.00,\"\"],[1620921600000,138.00,\"\"],[1621008000000,138.00,\"\"],[1621094400000,138.00,\"\"],[1621180800000,138.00,\"\"],[1621267200000,138.00,\"\"],[1621353600000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1621440000000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1621526400000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1621612800000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1621699200000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1621785600000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1621872000000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1621958400000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1622044800000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1622131200000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1622217600000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1622304000000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1622390400000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1622476800000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1622563200000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1622649600000,138.0,\"\"],[1622736000000,116.33,\"购买3,当前价:138.0,可叠加满减:每满20030,优惠券:满995\"],[1622822400000,116.33,\"购买3,当前价:138.0,可叠加满减:每满20030,优惠券:满995\"],[1622908800000,116.33,\"购买3,当前价:138.0,可叠加满减:每满20030,优惠券:满995\"],[1622995200000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1623081600000,133.0,\"购买1,当前价:138.0,优惠券:满995\"],[1623168000000,133.0,\"购买1,当前价:138.0,优惠券:满995\"]

便宜上、一部のみをコピーし、効果を試したい友達が試してみることができます。
この記事は以上です。気に入っていただけましたら、保存と注目にご協力ください。ありがとうございました。
最後に、もう一度強調しますが、これほど多くのことを書いているのは、JS の逆学習と共有のためだけです。不適切な目的で使用しないでください~

おすすめ

転載: blog.csdn.net/qq_33129963/article/details/122291558