爬蟲cookie過期_python instagram 爬蟲

葉湘倫:【文字篇】如何系統地自學 Python??zhuanlan.zhihu.com

直接介紹一下具體的步驟以及注意點:

instagram 爬蟲注意點

  • instagram 的首頁數據是 服務端渲染的,所以首頁出現的 11 或 12 條數據是以 html 中的一個 json 結構存在的(additionalData), 之后的帖子加載才是走 ajax 請求的
  • 在 2019/06 之前,ins 是有反爬機制的,請求時需要在請求頭加了 'X-Instagram-GIS' 字段。其算法是:
    1、將 rhx_gis 和 queryVariables 進行組合
rhx_gis 可以在首頁處的 sharedData 這個 json 結構中獲得

2、然后進行 md5 哈希

e.g.

   queryVariables = '{"id":"' + user_id + '","first":12,"after":"' +cursor+ '"}'print(queryVariables)headers['X-Instagram-GIS'] = hashStr(GIS_rhx_gis + ":" + queryVariables)
  • 但是在在 2019/06 之后, instagram 已經取消了 X-Instagram-GIS 的校驗,所以無需再生成 X-Instagram-GIS,上一點內容可以當做歷史來了解了
  • 初始訪問 ins 首頁的時候會設置一些 cookie,設置的內容 (response header) 如下:
   set-cookie: rur=PRN; Domain=.instagram.com; HttpOnly; Path=/; Secureset-cookie: ds_user_id=11859524403; Domain=.instagram.com; expires=Mon, 15-Jul-2019 09:22:48 GMT; Max-Age=7776000; Path=/; Secureset-cookie: urlgen="{"45.63.123.251": 20473}:1hGKIi:7bh3mEau4gMVhrzWRTvtjs9hJ2Q"; Domain=.instagram.com; HttpOnly; Path=/; Secureset-cookie: csrftoken=Or4nQ1T3xidf6CYyTE7vueF46B73JmAd; Domain=.instagram.com; expires=Tue, 14-Apr-2020 09:22:48 GMT; Max-Age=31449600; Path=/; Secure
  • 關于 query_hash,一般這個哈希值不用怎么管,可以直接寫死
  • 特別注意:在每次請求時務必帶上自定義的 header,且 header 里面要有 user-agent,這樣子才能使用 rhx_gis 來進行簽名訪問并且獲取到數據。切記!是每次訪問!例如:
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}

大部分 api 的訪問需要在請求頭的 cookie 中攜帶 session-id 才能得到數據,一個正常的請求頭 (request header) 如下:

   :authority: www.instagram.com:method: GET:path: /graphql/query/?query_hash=ae21d996d1918b725a934c0ed7f59a74&variables=%7B%22fetch_media_count%22%3A0%2C%22fetch_suggested_count%22%3A30%2C%22ignore_cache%22%3Atrue%2C%22filter_followed_friends%22%3Atrue%2C%22seen_ids%22%3A%5B%5D%2C%22include_reel%22%3Atrue%7D:scheme: httpsaccept: */*accept-encoding: gzip, deflate, braccept-language: zh-CN,zh;q=0.9,en;q=0.8,la;q=0.7cache-control: no-cachecookie: mid=XI-joQAEAAHpP4H2WkiI0kcY3sxg; csrftoken=Or4nQ1T3xidf6CYyTE7vueF46B73JmAd; ds_user_id=11859524403; sessionid=11859524403%3Al965tcIRCjXmVp%3A25; rur=PRN; urlgen="{"45.63.123.251": 20473}:1hGKIj:JvyKtYz_nHgBsLZnKrbSq0FEfeg"pragma: no-cachereferer: https://www.instagram.com/user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36x-ig-app-id: 936619743392459x-instagram-gis: 8f382d24b07524ad90b4f5ed5d6fccdbx-requested-with: XMLHttpRequest
  • 注意 user-agent、x-ig-app-id (html 中的 sharedData 中獲取)、x-instagram-gis,以及 cookie 中的 session-id 配置
api 的分頁 (請求下一頁數據),如用戶帖子列表
ins 中一個帶分頁的 ajax 請求,一般請求參數會類似下面:# 網頁頁面信息page_info = js_data["entry_data"]["ProfilePage"][0]["graphql"]["user"]["edge_owner_to_timeline_media"]['page_info']# 下一頁的索引值AQCSnXw1JsoV6LPOD2Of6qQUY7HWyXRc_CBSMWB6WvKlseC-7ibKho3Em0PEG7_EP8vwoXw5zwzsAv_mNMR8yX2uGFZ5j6YXdyoFfdbHc6942wcursor = page_info['end_cursor']# 是否有下一頁flag = page_info['has_next_page']
  • end_cursor 即為 after 的值,has_next_page 檢測是否有下一頁
    如果是有下一頁,可進行第一次分頁數據請求,第一次分頁請求的響應數據回來之后,id,first 的值不用變,after 的值變為響應數據中 page_info 中 end_cursor 的值,再構造 variables,連同 query_hash 發起再下一頁的請求
    再判斷響應數據中的 page_info 中 has_next_page 的值,循環下去,可拿完全部數據。若不想拿完,可利用響應數據中的 edge_owner_to_timeline_media 中的 count 值來做判斷,該值表示用戶總共有多少媒體
  • 視頻帖子和圖片帖子數據結構不一樣,注意判斷響應數據中的 is_video 字段
  • 如果是用一個 ins 賬號去采集的話,只要請求頭的 cookie 中帶上合法且未過期的 session_id,可直接訪問接口,無需計算簽名。
    最直接的做法是:打開瀏覽器,登錄 instagram 后,F12 查看 xhr 請求,將 request header 中的 cookie 復制過來使用即可,向下面:
# -*- coding:utf-8 -*-
import requests
import re
import json
import urllib.parse
import hashlib
import sysUSER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'BASE_URL = 'https://www.instagram.com'
ACCOUNT_MEDIAS = "http://www.instagram.com/graphql/query/?query_hash=42323d64886122307be10013ad2dcc44&variables=%s"
ACCOUNT_PAGE = 'https://www.instagram.com/%s'proxies = {'http': 'http://127.0.0.1:1087','https': 'http://127.0.0.1:1087',
}# 一次設置proxy的辦法,將它設置在一次session會話中,這樣就不用每次都在調用requests的時候指定proxies參數了
# s = requests.session()
# s.proxies = {'http': '121.193.143.249:80'}def get_shared_data(html=''):"""get window._sharedData from page,return the dict loaded by window._sharedData str"""if html:target_text = htmlelse:header = generate_header()response = requests.get(BASE_URL, proxies=proxies, headers=header)target_text = response.textregx = r"s*.*s*<script.*?>.*_sharedDatas*=s*(.*?);</script>"match_result = re.match(regx, target_text, re.S)data = json.loads(match_result.group(1))return data# def get_rhx_gis():
#     """get the rhx_gis value from sharedData
#     """
#     share_data = get_shared_data()
#     return share_data['rhx_gis']def get_account(user_name):"""get the account info by username:param user_name::return:"""url = get_account_link(user_name)header = generate_header()response = requests.get(url, headers=header, proxies=proxies)data = get_shared_data(response.text)account = resolve_account_data(data)return accountdef get_media_by_user_id(user_id, count=50, max_id=''):"""get media info by user id:param id::param count::param max_id::return:"""index = 0medias = []has_next_page = Truewhile index <= count and has_next_page:varibles = json.dumps({'id': str(user_id),'first': count,'after': str(max_id)}, separators=(',', ':'))  # 不指定separators的話key:value的:后會默認有空格,因為其默認separators為(', ', ': ')url = get_account_media_link(varibles)header = generate_header()response = requests.get(url, headers=header, proxies=proxies)media_json_data = json.loads(response.text)media_raw_data = media_json_data['data']['user']['edge_owner_to_timeline_media']['edges']if not media_raw_data:return mediasfor item in media_raw_data:if index == count:return mediasindex += 1medias.append(general_resolve_media(item['node']))max_id = media_json_data['data']['user']['edge_owner_to_timeline_media']['page_info']['end_cursor']has_next_page = media_json_data['data']['user']['edge_owner_to_timeline_media']['page_info']['has_next_page']return mediasdef get_media_by_url(media_url):response = requests.get(get_media_url(media_url), proxies=proxies, headers=generate_header())media_json = json.loads(response.text)return general_resolve_media(media_json['graphql']['shortcode_media'])def get_account_media_link(varibles):return ACCOUNT_MEDIAS % urllib.parse.quote(varibles)def get_account_link(user_name):return ACCOUNT_PAGE % user_namedef get_media_url(media_url):return media_url.rstrip('/') + '/?__a=1'# def generate_instagram_gis(varibles):
#     rhx_gis = get_rhx_gis()
#     gis_token = rhx_gis + ':' + varibles
#     x_instagram_token = hashlib.md5(gis_token.encode('utf-8')).hexdigest()
#     return x_instagram_tokendef generate_header(gis_token=''):# todo: if have session, add the session key:value to headerheader = {'user-agent': USER_AGENT,}if gis_token:header['x-instagram-gis'] = gis_tokenreturn headerdef general_resolve_media(media):res = {'id': media['id'],'type': media['__typename'][5:].lower(),'content': media['edge_media_to_caption']['edges'][0]['node']['text'],'title': 'title' in media and media['title'] or '','shortcode': media['shortcode'],'preview_url': BASE_URL + '/p/' + media['shortcode'],'comments_count': media['edge_media_to_comment']['count'],'likes_count': media['edge_media_preview_like']['count'],'dimensions': 'dimensions' in media and media['dimensions'] or {},'display_url': media['display_url'],'owner_id': media['owner']['id'],'thumbnail_src': 'thumbnail_src' in media and media['thumbnail_src'] or '','is_video': media['is_video'],'video_url': 'video_url' in media and media['video_url'] or ''}return resdef resolve_account_data(account_data):account = {'country': account_data['country_code'],'language': account_data['language_code'],'biography': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['biography'],'followers_count': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['edge_followed_by']['count'],'follow_count': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['edge_follow']['count'],'full_name': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['full_name'],'id': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['id'],'is_private': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['is_private'],'is_verified': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['is_verified'],'profile_pic_url': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['profile_pic_url_hd'],'username': account_data['entry_data']['ProfilePage'][0]['graphql']['user']['username'],}return accountaccount = get_account('shaq')result = get_media_by_user_id(account['id'], 56)media = get_media_by_url('https://www.instagram.com/p/Bw3-Q2XhDMf/')print(len(result))
print(result)

封裝成庫了!

如果還有問題未能得到解決,搜索887934385交流群,進入后下載資料工具安裝包等。最后,感謝觀看!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457396.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457396.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457396.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

php 無限循環

<?php header("Content-type:text/html;charsetutf-8"); $arr array( array(1, 0, 語文), array(2, 1, 數學), array(3, 0, 英文), array(4, 3, 美術), ); function xunhuan($pid 0) { global $arr; foreach ($arr as $value) { if ($value[1] $pid) { ech…

MySQL InnoDB 是如何存儲數據的

InnoDB 是怎么存儲數據的 本文是《MySQL 是怎樣運行的 —— 從根兒上理解 MySQL》讀書總結&#xff0c;強烈推薦這本書&#xff1b; CSDN 不能顯示 SVG&#xff0c;可能有圖片加載不出來&#xff0c;可以到 我的博客 上看。 數據目錄 眾所周之&#xff0c;MySQL 的數據是存儲在…

蔬菜大棚成本_蔬菜大棚種植成本和利潤究竟如何?種植戶有話說

大棚蔬菜種植&#xff0c;到底利潤高不高&#xff0c;就讓親身體驗過的人來說下自己的情況吧。農大老家山東也是大棚蔬菜種植比較早的地方&#xff0c;直到現在大棚種植蔬菜在各地都還是不少。大棚蔬菜種植&#xff0c;是有相應的補貼政策&#xff0c;在農業種植當中&#xff0…

WebSocket實戰之————GatewayWorker使用筆記例子

參考文檔&#xff1a;http://www.workerman.net/gatewaydoc/ 目錄結構 ├── Applications // 這里是所有開發者應用項目 │ └── YourApp // 其中一個項目目錄&#xff0c;目錄名可以自定義 │ ├── Events.php // 開發者只需要關注這個文件 │ ├── st…

[轉]關于凸優化的一些簡單概念

沒有系統學過數學優化&#xff0c;但是機器學習中又常用到這些工具和技巧&#xff0c;機器學習中最常見的優化當屬凸優化了&#xff0c;這些可以參考Ng的教學資料&#xff1a;http://cs229.stanford.edu/section/cs229-cvxopt.pdf&#xff0c;從中我們可以大致了解到一些凸優化…

Go 1.18.1 Beta 嘗鮮 泛型 FuzzTest workspace mode

Go 1.18.1 Beta 嘗鮮 昨天&#xff0c;go 終于發布了 1.18 的 beta 版本, 帶來了大家期待已久的泛型&#xff0c;抓緊時間康康能不能趕上熱乎的。 下載地址 根據社區昨天發的 Go 1.18 Beta 1 is available, with generics 這次版本更新主要帶來的新功能有&#xff1a; 泛型模…

centos7部署兩個mysql_一文掌握mysql實用工具--pt-online-schema-change、innotop部署

概述因為OSC和innotop這兩個需要的依賴包比較接近&#xff0c;所以這次就寫一起了&#xff0c;下面介紹下完整的部署教程&#xff0c;以下基于centos7操作系統。官網文檔&#xff1a;http://dev.mysql.com/doc/refman/5.7/en/innodb-create-index-overview.htmlOSC&#xff1a;…

python面試題目

問題一&#xff1a;以下的代碼的輸出將是什么? 說出你的答案并解釋。 1234567891011121314class Parent(object):x 1class Child1(Parent):passclass Child2(Parent):passprint Parent.x, Child1.x, Child2.xChild1.x 2print Parent.x, Child1.x, Child2.xParent.x 3print …

修改頁面后獲得flag_互動征集丨是時候為2021立flag了

2020馬上就要過去了今年的flag各位小伙伴實現了多少&#xff1f;翻出了生灰的flag擦擦說不定2021還能接著用哦2020年就要過去了還記得你在年初立下的那些Flag嗎&#xff1f;減肥“明天我就開始減肥&#xff01;”是大部分人在大部分時候都掛在嘴邊的一句話疫情宅家不僅沒減成還…

Python3.10 結構化模式匹配 PEP 634

Python3.10 結構化模式匹配 PEP 634 眼看 2021 馬上結束&#xff0c;python 發布了它的 3.10 版本&#xff0c;優化了錯誤消息&#xff0c;上下文管理器等內容&#xff0c;但更吸引我的還是結構化模式匹配。 眾所周之 switch 一直是 python 社區呼聲比較高的一個功能&#xff…

為ESXI 添加ISCSI存儲設備 Linux服務器系統

為ESXI 添加ISCSI存儲設備 Linux系統本文使用的LINUX 6系統上一塊硬盤制作的ISCSI存儲設備其IP地址為&#xff1a;192.168.26.218:在系統上直接輸入&#xff1a;yum -y install scsi-target-utils 命令 安裝 iscsi分區設置我們將SDD這塊硬盤的SDD1作為iscsi存儲設備編輯ISCSI配…

出棧順序 與 卡特蘭數(Catalan)的關系

一&#xff0c;問題描述 給定一個以字符串形式表示的入棧序列&#xff0c;請求出一共有多少種可能的出棧順序&#xff1f;如何輸出所有可能的出棧序列&#xff1f; 比如入棧序列為&#xff1a;1 2 3 &#xff0c;則出棧序列一共有五種&#xff0c;分別如下&#xff1a;1 2 3、…

[譯] Bounds Check Elimination 邊界檢查消除

[譯] Bounds Check Elimination 邊界檢查消除 Go 是一種內存安全的語言&#xff0c;在針對數組 (array) 或 Slice 做索引和切片操作時&#xff0c;Go 的運行時&#xff08;runtime&#xff09;會檢查所涉及的索引是否超出范圍。如果索引超出范圍&#xff0c;將產生一個 Panic&…

cad多段線畫圓弧方向_CAD箭頭怎么畫

CAD箭頭怎么畫問&#xff1a;CAD箭頭怎么畫&#xff1f;答&#xff1a;想要回答CAD箭頭怎么畫這個問題&#xff0c;得先從CAD多段線命令說起&#xff0c;畫箭只是多段線的一種應用。執行CAD多段線命令的三種方式1.單擊菜單欄上的"繪圖">>"多段線"。2…

HDU 5410 CRB and His Birthday ——(完全背包變形)

對于每個物品&#xff0c;如果購買&#xff0c;價值為A[i]*xB[i]的背包問題。 先寫了一發是WA的 。代碼如下&#xff1a; 1 #include <stdio.h>2 #include <algorithm>3 #include <string.h>4 #include <set>5 using namespace std;6 typedef pair<…

一篇講Java指令重排和內存可見性的好文

在這里&#xff1a; http://tech.meituan.com/java-memory-reordering.html 指令重排和內存可見性&#xff08;緩存不一致&#xff09;是兩個不同的問題。 volatile關鍵字太強&#xff0c;即阻擋指令重排&#xff0c;又保證內存一致性。 unsafe.putOrderedXXX()只阻擋指令重排&…

php 獲取delete蠶絲_php結合Redis實現100萬用戶投票項目,并實時查看到投票情況的案例...

場景&#xff1a;某網站需要對其項目做一個投票系統&#xff0c;投票項目上線后一小時之內預計有100萬用戶進行投票&#xff0c;希望用戶投票完就能看到實時的投票情況這個場景可以使用redismysql冷熱數據交換來解決。何為冷熱數據交換&#xff1f;冷數據&#xff1a;之前使用的…

硬件內存模型 Hardware Memory Models

硬件內存模型 Hardware Memory Models (Memory Models, Part 1) Posted on Tuesday, June 29, 2021. 簡介&#xff1a;童話的終結 很久以前&#xff0c;當人們還在寫單線程程序的時候&#xff0c;讓程序跑的更快的一個最有效的辦法就是什么也不做&#xff0c;因為下一代硬件…

碰到日期題就怕的我來寫一道水題吧

HDOJ-2005&#xff0c; http://acm.hdu.edu.cn/showproblem.php?pid2005 20XX系列的水題哈哈&#xff0c;寫了二十分鐘&#xff0c;就為找到一種比較正常不傻逼的寫法。。。 嗯&#xff0c;學習了一下&#xff0c;閏年的判斷可以寫成一個接受參數的宏。 #define lev(n) (n%40&…

判斷是否為gif/png圖片的正確姿勢

判斷是否為gif/png圖片的正確姿勢 1.在能取到圖片后綴的前提下 123456789//假設這是一個網絡獲取的URLNSString *path "http://pic3.nipic.com/20090709/2893198_075124038_2.gif";// 判斷是否為gifNSString *extensionName path.pathExtension;if ([extensionName…