title: golang爬取Instagram内容下载地址
tags: go
author: Clown95


前言

应该是全网首发吧???如果转载请添加原作者信息。

因为工作需要,需要获取一些小姐姐的图片和视频,然后就瞄上了ins。虽然可以利用一些插件保存图片和视频,但是这种方法不仅效率低,而且繁琐。因此就想通过程序来实现,搜索了一圈也没找到什么好的ins下载器,果断自己撸一个。

其实ins获取到它的内容并不难,它就是使用json传递了信息。但是如果想要获得全部内容就比较麻烦,它的内容是通过动态加载的,没有什么翻页的参数,所以想要获得到全部内容需要动一点脑筋。

分析

首先我们来分析一下如何获得ins的图片和视频地址,前提是你得有一个科学上网的梯子。

json地址参数分析

我们随机选择找一个小姐姐的主页

https://www.instagram.com/angelaqiqi_99/

通过浏览器的开发者工具,我们可以看到ins传递了一些json信息

我们选择最后一个json地址,并把这个它解码一下看看它有什么信息

https://www.instagram.com/graphql/query/?query_hash=44efc15d3c13342d02df0b5a9fa3d33f&variables={“id”:“436245394”,“first”:12,“after”:“QVFENGZuREJpVFhrakVkdEc0cGpUTmI2XzNzWi1fQ1NJYWM4MTh4M0MzMDNNc3VWM2hzVkRmUEZXMW54REV5ZjZfWl8tMlh4UmkySVpTTEtJcUs0OEVWWg==”}

我们通过这个地址可以看到,它与两个参数query_hashvariablesvariables里面又包含了三个参数分别是idfirstafter ,并且通过这个名字我们可以知道,网站数据的变化跟它有关系。。

然后我们滚动网页,查看下一个json的地址有什么不一样的地方

我们还是来看一下解码后的地址:

https://www.instagram.com/graphql/query/?query_hash=44efc15d3c13342d02df0b5a9fa3d33f&variables={“id”:“436245394”,“first”:12,“after”:“QVFEX3VVWjZEcExrbmxWdUZfQUMzeUEzdnd1UTZPSU1FQllMRVNDSmdBeVJCRVlVVE80eS1rcmdKcmlUT0lwRENsZ0xac2k4cmxEVlR5R0FwZTNiX3ZKYQ==”}

通过对比我们发现,after这个产生不一样,其他几个都一样。 接下来我们猜测一下这些参数的用途。

  • query_hash是查询数据的hash值(这个值是固定的,ins会隔一段时间更换一次,可能是一个月,也可能是两个月)
  • id是博主的账号id
  • first是每次显示内容的数量
  • after根据名字猜测,在…之后,说明它是类似于索引的东西,主要用来控制数据加载的

图片和视频地址分析

现在我们已经知道了所有参数的用途,现在我们来具体的看下json的内容,我们以第二个地址为例

通过图片我们可以看到, display_url它存放了一个图片的地址。is_video通过意思我们可以知道它用来判断内容是否为视频。

我们在找一段is_videotrue验证一下我们的想法。

果不其然,is_videotrue的情况下,多了一个键video_url,不用看都知道这是存放视频地址的, display_url这时候是这个视频的封面图片。

知道了这三个键,那么我们在进行数据获取的就可以通过is_video来屏蔽掉视频封面的图片。

内容加载分析

现在我们已经知道了图片和视频的存放地址,接下来才是重点,ins是如何加载更多内容的。前面我们猜测过after这个参数是控制内容加载的。

现在我们已经知道了after参数的用途,现在我们就需要找到它是在什么地方传递的。已知第一个after的值为QVFENGZuREJpVFhrakVkdEc0cGpUTmI2XzNzWi1fQ1NJYWM4MTh4M0MzMDNNc3VWM2hzVkRmUEZXMW54REV5ZjZfWl8tMlh4UmkySVpTTEtJcUs0OEVWWg=="

我们在源文件里面搜索它,果然我们在script里面搜索到了它,只不过它的键名是end_cursor ,看到这么名字你是不是已经猜到了什么,结束游标,它就是我们要找的那个。

如果你仔细的看了json的内容,那么你应该对它有印象。

在json中page_info里面包含了has_next_pageend_cursor

  • has_next_page 判断是否有下一页
  • end_cursor 当前页的结束游标

当然一个json里面包含了好几个page_info,最主要的就是第一个page_info,这个我已经验证过。当主要数据到底的时候,只有这个page_infoend_cursor内容为空。

现在我们已经知道了第一页的end_cursorscript里面,第二页的end_cursor在第一条josn里面,以此类推,第三页的end_cursor,在第二条josn里面。

实现

package mainimport ("bufio""encoding/json""fmt""io/ioutil""log""net/http""net/url""os""regexp""strconv""time"
)type Instargam struct {Data struct {User struct {EdgeOwnerToTimelineMedia struct {//Count int `json:"count"`Edges []struct {Node struct {/*DashInfo struct {IsDashEligible    bool   `json:"is_dash_eligible"`NumberOfQualities int  `json:"number_of_qualities"`VideoDashManifest string `json:"video_dash_manifest"`} `json:"dash_info"`EdgeMediaToComment struct {PageInfo struct {EndCursor string `json:"end_cursor"`} `json:"page_info"`} `json:"edge_media_to_comment"`*/DisplayURL            string `json:"display_url"`EdgeSidecarToChildren struct {Edges []struct {Node struct {/*DashInfo struct {VideoDashManifest string `json:"video_dash_manifest"`} `json:"dash_info"`*/DisplayURL string `json:"display_url"`IsVideo    bool   `json:"is_video"`VideoURL   string `json:"video_url"`} `json:"node"`} `json:"edges"`} `json:"edge_sidecar_to_children"`IsVideo  bool   `json:"is_video"`VideoURL string `json:"video_url"`} `json:"node"`} `json:"edges"`PageInfo struct {EndCursor   string `json:"end_cursor"`HasNextPage bool   `json:"has_next_page"`} `json:"page_info"`} `json:"edge_owner_to_timeline_media"`} `json:"user"`} `json:"data"`
}// 获取网页源代码
func GetHtml(Insurl string) (html string) {// 解析代理地址proxy, err := url.Parse("http://127.0.0.1:1087") //加载本地代理//设置网络传输netTransport := &http.Transport{Proxy:                 http.ProxyURL(proxy),MaxIdleConnsPerHost:   10,ResponseHeaderTimeout: time.Second * time.Duration(5),}httpClient := &http.Client{Timeout:   time.Second * 10,Transport: netTransport,}request, err := http.NewRequest("GET", Insurl, nil)if err != nil {log.Println(err)}request.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36") //模拟浏览器User-Agentrequest.Header.Set("Cookie", `ig_did=5448DAB0-E424-48F9-97DF-3A386834D9BE; mid=XsH7PQAEAAG55HTxRZVxBxvZICeY; ds_user_id=25850748707; shbid=2673; shbts=1590030929.7257333; csrftoken=OvLzaajy6C9peOrWQeTfo61GBRY0xLGz; sessionid=25850748707%3ATgB2CXKqw4BFUu%3A23; rur=FTW; urlgen="{\"35.221.222.156\": 15169\054 \"34.92.32.194\": 15169\054 \"34.92.235.238\": 15169}:1jcJdR:nlKH_w6YMze8RyJkjEbQ5Sc9UxA"`)res, err := httpClient.Do(request)if err != nil {log.Println(err)return}defer res.Body.Close()//判断是否成功访问,如果成功访问StatusCode应该为200if res.StatusCode != http.StatusOK {log.Println(err)return}content, _ := ioutil.ReadAll(res.Body)return string(content)
}// 通过主页获取第一个after的值
func GetAfterByHtml(homepage string) string {regex := `end_cursor":"(.*?)"},"edges`rp := regexp.MustCompile(regex)after := rp.FindStringSubmatch(homepage)return after[1]
}// 通过主页获得博主的账号ID
func GetIdByHtml(homepage string) string {regex := `{"id":"(.*?)","username`rp := regexp.MustCompile(regex)id := rp.FindStringSubmatch(homepage)return id[1]
}//获取博主的账号名
func GetUserName(homepage string) string {l1 := len("https://www.instagram.com/")l2 := len(homepage)return homepage[l1:l2-1] + ".txt"
}// 拼接查询地址
func SetQueryUrl(query_hash, id, first, after string) string {url := fmt.Sprintf("https://www.instagram.com/graphql/query/?query_hash=%s&variables={\"id\":\"%s\",\"first\":%s,\"after\":\"%s\"}", query_hash, id, first, after)return url
}//json转Struct
func Json2Struct(strjson string) Instargam {var ins Instargamjson.Unmarshal([]byte(strjson), &ins)return ins
}//通过json得到After
func GetAfter(ins Instargam) string {return ins.Data.User.EdgeOwnerToTimelineMedia.PageInfo.EndCursor
}// 判断网站是否加载到底
func IsEnd(ins Instargam) bool {return ins.Data.User.EdgeOwnerToTimelineMedia.PageInfo.HasNextPage
}// 通过json得到图片和视频下载地址
func GetDownloadUrl(savefile string, ins Instargam) {for _, v := range ins.Data.User.EdgeOwnerToTimelineMedia.Edges {var content stringif v.Node.IsVideo != true {fmt.Println(v.Node.DisplayURL)content = v.Node.DisplayURL + "\n"} else {fmt.Println(v.Node.VideoURL)content += v.Node.VideoURL + "\n"}for _, v1 := range v.Node.EdgeSidecarToChildren.Edges {if v1.Node.IsVideo != true {fmt.Println(v1.Node.DisplayURL)content = v1.Node.DisplayURL + "\n"} else {fmt.Println(v1.Node.VideoURL)content += v1.Node.VideoURL + "\n"}}WirteText(savefile, content)}
}// 写入txt文件
func WirteText(savefile string, txt string) {f, err := os.OpenFile(savefile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)if err != nil {fmt.Println("os Create error: ", err)return}defer f.Close()bw := bufio.NewWriter(f)bw.WriteString(txt)bw.Flush()
}func main() {var homepage stringfmt.Scanln(&homepage)query_hash := "44efc15d3c13342d02df0b5a9fa3d33f"first := 12//通过html获取第一条json地址html := GetHtml(homepage)after := GetAfterByHtml(html)id := GetIdByHtml(html)first_query_url := SetQueryUrl(query_hash, id, strconv.Itoa(first), after) //  第一条json地址//通过json获取内容jsonconent := GetHtml(first_query_url)for {ins := Json2Struct(jsonconent)next_after := GetAfter(ins) //通过json获得after的值next_query_url := SetQueryUrl(query_hash, id, strconv.Itoa(first), next_after)GetDownloadUrl(GetUserName(homepage), ins)jsonconent = GetHtml(next_query_url)if !IsEnd(ins) { //如果页面加载到底,结束循环break}}}

golang爬取Instagram内容下载地址相关推荐

  1. python爬取Instagram上偶像的帖子(包括图片和视频)

    python爬取Instagram上偶像的帖子(包括图片和视频) 声明:仅供技术交流,请勿用于非法用途,如有其它非法用途造成损失,和本博客无关 目录 python爬取Instagram上偶像的帖子(包 ...

  2. python输入数据爬取_python根据用户需求输入想爬取的内容及页数爬取图片方法详解...

    本次小编向大家介绍的是根据用户的需求输入想爬取的内容及页数. 主要步骤: 1.提示用户输入爬取的内容及页码. 2.根据用户输入,获取网址列表. 3.模拟浏览器向服务器发送请求,获取响应. 4.利用xp ...

  3. Python爬虫:爬取instagram,破解js加密参数

    Python爬虫:爬取instagram,破解js加密参数 instagram 是国外非常流行的一款社交网站,类似的还有像facebook.twitter,这些社交网站对于掌握时事热点.电商数据来源和 ...

  4. python爬取网页内容requests_[转][实战演练]python3使用requests模块爬取页面内容

    本文摘要: 1.安装pip 2.安装requests模块 3.安装beautifulsoup4 4.requests模块浅析 + 发送请求 + 传递URL参数 + 响应内容 + 获取网页编码 + 获取 ...

  5. python爬去新浪微博_Python爬虫爬取新浪微博内容示例【基于代理IP】

    Python爬虫爬取新浪微博内容示例[基于代理IP] 发布时间:2020-09-07 10:08:14 来源:脚本之家 阅读:120 本文实例讲述了Python爬虫爬取新浪微博内容.分享给大家供大家参 ...

  6. 爬虫学习(一)---爬取电影天堂下载链接

    欢迎加入python学习交流群 667279387 爬虫学习 爬虫学习(一)-爬取电影天堂下载链接 爬虫学习(二)–爬取360应用市场app信息 主要利用了python3.5 requests,Bea ...

  7. 我用Python爬取了难下载的电子教材(内附代码)

    我用Python爬取了难下载的电子教材(内附代码) 第一次在CSDN上面分享经历,有点激动.本大二狗最近这段时间去不了学校又想看教材,不巧学习通上面的部分内容老师设置了不可下载啊.好在最近学习了一点P ...

  8. python爬取微博文本_Python爬虫爬取新浪微博内容示例【基于代理IP】

    本文实例讲述了Python爬虫爬取新浪微博内容.分享给大家供大家参考,具体如下: 用Python编写爬虫,爬取微博大V的微博内容,本文以女神的微博为例(爬新浪m站:https://m.weibo.cn ...

  9. python爬虫下载小说_python 爬取小说并下载的示例

    代码 import requests import time from tqdm import tqdm from bs4 import BeautifulSoup """ ...

  10. python 爬取数据还要下载scrapy吗_python网络爬虫之Scrapy

    本文分享的大体框架包含以下三部分 (1)首先介绍html网页,用来解析html网页的工具xpath (2)介绍python中能够进行网络爬虫的库(requests,lxml,scrapy等) (3)从 ...

最新文章

  1. Lambda 表达式有何用处?如何使用?
  2. Hystrix的应用案例:多短信供应商的自动切换与恢复
  3. 比较经典的三层交换机实验
  4. hdu1287 破译密码
  5. 文件管理服务器数据库,会博通系统的海量数据库管理策略
  6. idea上一些比较有用的插件
  7. Android 基础教程之-------Android ProgressBar的使用!
  8. 信息学奥赛一本通C++语言——1009:带余除法
  9. 安卓马赛克view_Android马赛克效果MosaicView
  10. 机器学习-多元梯度下降
  11. BZOJ3653: 谈笑风生
  12. Spring中com.sun.proxy.$Proxy12 cannot be cast to 包名.类名错误
  13. Julia : 在编程中的Unicode 字符
  14. android viewflipper 动画,Android ViewFlipper动画
  15. 《郝斌C语言自学教程》课程大纲
  16. 联机饥荒一直显示启动服务器,饥荒联机版启动服务器时遇到一些麻烦 | 手游网游页游攻略大全...
  17. 计算机组成x什么意思,cpu后面带x是什么意思
  18. android渠道首发规则,酷传推广标准手册-android渠道首发规则.doc
  19. 踩坑记---Win10安装anaconda及tensorflow-cpu版
  20. 网站地图是什么?该如何生成

热门文章

  1. TCPIP协议详解内容总结
  2. 实验二:递归下降语法分析
  3. FPGA(二)---38译码器
  4. 11计算机专业vb试题答案,11高三计算机专业VB试题(三)
  5. Golang项目:客户信息管理系统(附源码) (Golang经典编程案例)
  6. 蚂蚁金服Java面试题、笔试题(含答案)-高级
  7. 计算机快捷指令ip,IP小技巧之如何使用DOS命令行快速修改电脑IP地址?
  8. java多线程编程实例
  9. 易语言手动和代码创建数据库
  10. 基于西储大学的轴承故障诊断系统设计