このブログ投稿に書かれているクロールルールの最新の更新日は次のとおりです。2021-2-28
注意:転載のために著者と元のリンクを示してください!!!
CSDN個人ホームページ: 高IQ馬鹿
元のアドレス: https ://blog.csdn.net/qq_44700693/article/details/113826111
小寒暄
このセクションを見ている友達が、私が以前に書いたPythonクローラーを見たことがあるかどうかはわかりません:透かしなしのピッピエビの短いビデオのダウンロード。
この記事では、共有リンクを開いて透かしリクエストAPIのないWebバージョンのビデオを見つけましたが、長くは続かず、数か月後に期限切れになりました。
以前にそれを行った理由は、ブラウザでビデオ共有リンクを開くと、ビデオ自体のWebバージョンが透かしなしでビデオをロードすることがわかったためです。もちろん、Webページを解析するのが最善ですが、今は、Webページクライアント側のビデオは、ウォーターマーク付きのビデオとして自動的にロードされ、ウォーターマーク付きのビデオインターフェイスのない元のWebページのビデオリンクフィールドもnull値になりました。
これまで多くの方から、最新の分析方法があるかどうかのプライベートメッセージが届きました。その後、Web版を調べましたが、うまくいきませんでした。パラメータの暗号化なのか、リクエストフィールドの意味なのか。 、私は途方に暮れています。
分析プロセス
小さな挨拶の中で、以前にWebバージョンのインターフェイスを解析することを選択した理由は、ビデオ自体のWebバージョンが透かしなしでビデオをロードするためであると述べたので、Webバージョンを直接解析することを選択しました。携帯電話のWebバージョンまたはコンピュータビデオのWebバージョンはすべて透かし付きのロードされたビデオであるため、今回はAPPから直接開始します。
開始するためのヒント: PippiShrimpのAndroidクライアントは証明書にロックされています。そして、この問題を解決する方法については、私のNingブログ投稿「Fiddler:Fiddlerの新旧バージョンの概要」を参照してください。
パケットキャプチャ構成:
Fiddler Everywhere
Night God Emulator(Android 5)
证书锁定(SSL/TLS Pinning)顾名思义,将服务器提供的SSL/TLS证书内置到移动端开发的APP客户端中,当客户端发起请求时,通过比对内置的证书和服务器端证书的内容,以确定这个连接的合法性。
すべての準備ができたら、パケットキャプチャ分析を開始できます。
ここでは、前の数回分析を試みたときに踏んだ大きな穴について言及する必要があります。それが私の原因なのか、このAPIなのかは本当にわかりません。。混乱しすぎます~~
私はほとんどの場合、次のAPIから開始します:
これは、このAPIの戻り本文に次の情報が見つかったためです:
origin_video_download !!!
これは、Webページの透かしのないビデオリンクフィールドではありません~~
何でも選択してくださいリンクがブラウザで開きます:それは
...成功しましたか???
成功したとしても、これらのパラメータは...リクエストヘッダーのフィールドは言うまでもなく、リクエストの本文だけで十分です。
自分で分析するのは経験に頼ることはできますが...とにかく失敗しました。
次に、少し気が進まないものの、次のいくつかの分析がここに植えられますが、それは真実です。
メインコード
そして、この時間は、私は新しいインターフェイスを見つけた:
次は、上記のパケットキャプチャに、我々はそれを開いた後、ソフトウェアをロードし、その後、削除されたすべてのパケットキャプチャ情報、および特定のビデオの詳細ページを入力するには、仮想マシン上でクリックした:
そして、パケットのキャプチャを停止します。
次に、貴重な情報をゆっくりと見つけます。
次に、APIを分析します。
ここでは、文字列を辞書にすばやく変換できる小さなスクリプトを作成しました。
import re def parse_header(s_header): form = { } s_h = re.findall(r'(.*?):(.*?)\n', s_header) for a in s_h: form[a[0].strip()] = a[1].strip() return form
必要に応じて直接使用できます。
だから私は次のバージョンのコードを手に入れました:
import requests
api_url = 'https://i-lq.snssdk.com/bds/cell/cell_comment/'
headers = {
'Accept-Encoding': 'gzip',
'X-SS-QUERIES': '******',
'X-SS-REQ-TICKET': '1614499328380',
'x-vc-bdturing-sdk-version': '2.0.1',
'passport-sdk-version': '30',
'sdk-version': '2',
'User-Agent': 'ttnet okhttp/3.10.0.2',
'Cookie': '******',
'X-Khronos': '1614499329',
'X-Gorgon': '040400a50005d14c4b04f9fa5ac0c9ec9617070b6fcfe1bff0f2',
'Host': 'i-lq.snssdk.com',
'Connection': 'Keep-Alive'}
param = {
'cell_type': '1',
'cell_id': '6884917158271260935',
'offset': '0',
'api_version': '1',
'iid': '1284657529238599',
'device_id': '1179092996603726',
'ac': 'wifi',
'mac_address': '54%3ABF%3A64%3A48%3A8C%3A87',
'channel': 'baidu',
'aid': '1319',
'app_name': 'super',
'version_code': '331',
'version_name': '3.3.1',
'device_platform': 'android',
'ssmix': 'a',
'device_type': 'LIO-AN00',
'device_brand': 'Android',
'language': 'zh',
'os_api': '22',
'os_version': '5.1.1',
'uuid': '863064547881401',
'openudid': '5c2a72be0ea16ab0',
'manifest_version_code': '331',
'resolution': '900*1600',
'dpi': '320',
'update_version_code': '33150',
'_rticket': '1614499328336',
'cdid': '6e3fcc11-5cc4-494f-acbe-d9887dd59e08',
'app_region': 'CN',
'sys_region': 'CN',
'time_zone': 'Asia%2FShanghai',
'app_language': 'ZH',
'carrier_region': 'CN',
'last_channel': '',
'last_update_version_code': '0',
'ts': '1614499328'
}
def parse_url():
response = requests.get(api_url, headers=headers, params=param)
video = response.json()['data']['cell_comments'][0]['comment_info']['item']['video']
video_name = video['text']
video_url = video['video_high']['url_list'][0]['url']
print("video_name:" + video_name)
print("video_url:" + video_url)
if __name__ == '__main__':
parse_url()
演算結果:
video_name:像极了当年没有手机的自己
video_url:http://v3-ppx.ixigua.com/a7e2629a5d88663e2f4ae8804fb67e01/603b62d7/video/m/220de8d705970384c929ba5f75e150f20b9116625db80000645ef6706767/?a=1319&br=1280&bt=320&cd=0%7C0%7C0&ch=0&cr=0&cs=0&cv=1&dr=6&ds=6&er=&l=202102281630490101351550433E018EB7&lr=&mime_type=video_mp4&pl=0&qs=0&rc=am80ZzNxamQ1eDMzaWYzM0ApPDU0NDdnaGQ8Nzw7ZzdnPGcyay5mZG8yNDNfLS1jMTBzczMzYC5gXmJjYDUyNGI2YjE6Yw%3D%3D&vl=&vr=
調べてみると、得られたリンクは確かに透かしの入っていないリンクなので、次のステップはパラメータを分析することです...
実際には分析する必要はありません〜
無効なパラメータがたくさんあります。コードの2番目のバージョンを取得します。
import requests
path = "./PPX/"
api_url = 'https://i-lq.snssdk.com/bds/cell/cell_comment/'
headers = {
'User-Agent': 'ttnet okhttp/3.10.0.2',
'Host': 'i-lq.snssdk.com',
'Connection': 'Keep-Alive'
}
param = {
'cell_id': '6884917158271260935',
'aid': '1319',
'app_name': 'super',
}
def parse_url():
response = requests.get(api_url, headers=headers, params=param)
video = response.json()['data']['cell_comments'][0]['comment_info']['item']['video']
video_name = video['text']
video_url = video['video_high']['url_list'][0]['url']
print("video_name:" + video_name)
print("video_url:" + video_url)
if __name__ == '__main__':
parse_url()
30行未満のコード...
より堅牢でフラットで共有リンクとの互換性を保つために、次の3番目のバージョンのコードがあります。
import random
import requests
path = "./PPX/"
class PpxNew:
api_url = 'https://i-lq.snssdk.com/bds/cell/cell_comment/'
headers = {
'User-Agent': 'ttnet okhttp/3.10.0.2',
'Host': 'i-lq.snssdk.com',
'Connection': 'Keep-Alive'
}
def __init__(self, s_url):
if '/item/' in s_url:
self.cell_id = s_url.split('?')[0].split('/')[-1]
elif '/s/' in s_url:
self.rel_url = requests.get(s_url, headers={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}).url
self.cell_id = self.rel_url.split('?')[0].split('/')[-1]
self.param = {
'cell_id': self.cell_id,
'aid': '1319',
'app_name': 'super',
}
def parse_url(self):
response = requests.get(self.api_url, headers=self.headers, params=self.param)
video = response.json()['data']['cell_comments'][0]['comment_info']['item']['video']
video_name = video['text']
if video_name == '':
video_name = int(random.random() * 2 * 1000)
if len(str(video_name)) > 20:
video_name = video_name[:20]
video_url = video['video_high']['url_list'][0]['url']
with open(path + str(video_name) + ".mp4", 'wb')as fp:
fp.write(requests.get(video_url).content)
print("【皮皮虾】: {}.mp4 无水印视频下载完成!".format(video_name))
if __name__ == '__main__':
s_url = 'https://h5.pipix.com/s/eJXwbxC/'
PpxNew(s_url).parse_url()