最近迷上了@桐谷美玲_MireiKiritani小姐姐的颜值,因而在Ins上也关注了一波,因而发现了一大波美图,但是ins出于版权方面的考虑并不在客户端和网页端直接提供图片的下载功能,因为以前学习python的最初阶段就学过爬虫,因而重操旧业打起了爬取美图的打算,也算是对python的一点复习吧。html
移动端操做不便,并且学校IPV6网络设置好hosts就能轻松访问ins(虽然有时候不太稳定,不过这几天好像还能够=,=),首选经过PC端网页爬取。前端
用Chrome打开ins以后按F12就能进入开发模式,选取上面的图片就能找到相应的图片入口,但打开相应的div能够发如今当前页面下的图片全都是缩略图,所能得到的最大分辨率仅为640*640。这显然不能达到要求(`・ω・´),因而我开始找原图的URL。python
还有一个问题就是ins上面的图片所有都是使用js动态生成的,也就意味着咱们在使用requests模块get到的内容仅仅是网页框架和一堆js脚本而已,对网页上的network进行监听就能看到js进行的xmlhttp requests.咱们甚至可以在xmlhttp requests中找到原始图片的URL,但问题就是这个xmlhttp requests在向服务器发送请求时须要一个Query String,里面有一串须要随机生成的variable。能够经过查找页面的js代码找到这串key的生成代码,但对于很久没用js的我来讲这段js代码无异于天书,感受看懂须要把前端的知识好好复习复习。在这里我显然并无这样的打算。web
页面xmlhttp-request加载chrome
js中variable生成的部分代码浏览器
咱们彷佛须要找到一个更可行的方法来得到ins上原始图片的URL,而这个方法就在这个页面上。咱们能够点开每一张图片从而到达图片详情页,而在详情页里面天然就有咱们所须要的原图URL。并且幸运的是在图片详情页的html中,咱们能够直接使用requests得到这个url!服务器
咱们须要下载图片就须要得到每张图片的URL,通过前面的讨论我已经大体肯定了URL获取方式:cookie
ins我的主页 --> ins图片详情页URL --> ins图片详情页 -->详情页中的原图URL网络
就像前面说到过的,ins我的主页上的图片是经过js动态生成的,这就意味着咱们没有办法经过requests简单的得到全部所需的URL,这时候对于并不精通js相关的我来讲也就只剩下selenium模拟浏览器这一条路了。关于selenium我在这里也不想多说,以前我也使用过,不过并不熟,配合着文档和Google也就能实现本身所须要的功能了。并发
整个技术思路就是经过selenium模拟浏览器行为得到ins我的主页上面关于全部图片详情页的URL,而后经过URL使用requests得到全部详情页的HTML,最后经过html解析模块得到相应原始图片url,最后直接使用requests下载图片。
很久没写Python和爬虫了,虽然大体过程仍是有数,但作起来仍是须要边测试边搜索文档,这里因为selenium与chrome的加入,对于一些设计网络和程序控制方面的东西仍是须要本身尝试。
import requests import time import os from lxml import etree from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains options = webdriver.ChromeOptions() options.add_argument('lang=zh_CN.UTF-8') driver = webdriver.Chrome(chrome_options = options) target = "https://www.instagram.com/mirei_kiritani_/" url_set = set([]) driver.get(target) url_set=set([])#set用来unique URL pic_index = 0 url_set_size = 0 save_dir = './pic/' if not os.path.exists(save_dir): os.mkdir(save_dir) header = { #requests header最好设置一下,不然服务器可能会拒绝访问 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7', 'cookie': 'shbid=4419; rur=PRN; mcd=3; mid=W1E7cAALAAES6GY5Dyuvmzfbywic; csrftoken=uVspLzRYlxjToqSoTlf09JVaA9thPkD0; urlgen="{\"time\": 1532050288\054 \"2001:da8:e000:1618:e4b8:8a3d:8932:2621\": 23910\054 \"2001:da8:e000:1618:6c15:ccda:34b8:5dc8\": 23910}:1fgVTv:SfLAhpEZmvEcJn0037FXFMLJr0Y"', 'referer': 'https://www.instagram.com/', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36', } while(True): divs = driver.find_elements_by_class_name('v1Nh3') #这里最好使用xxxx_by_class_name,我尝试过用xpath绝对路径,可是好像对于页面变化比较敏感 for u in divs: url_set.add(u.find_element_by_tag_name('a').get_attribute('href')) if len(url_set) == url_set_size: #若是本次页面更新没有加入新的URL则可视为到达页面底端,跳出 break url_set_size = len(url_set) ActionChains(driver).send_keys(Keys.PAGE_DOWN).perform()#三次滑动,保证页面更新足够 ActionChains(driver).send_keys(Keys.PAGE_DOWN).perform() ActionChains(driver).send_keys(Keys.PAGE_DOWN).perform() time.sleep(3) #下载图片: def pic_download(u_download): global pic_index rec = requests.get(u_download, headers = header) selector = etree.HTML(rec.content) meta = selector.xpath('/html/head/meta[10]')[0] #使用xpath解析页面 real_pic_url = meta.get("content").strip() pic_extend = real_pic_url[-4:] file_name = save_dir + "mirei_" + str(pic_index) + pic_extend pic_index += 1 f = open(file_name,'wb') pic_bin = requests.get(real_pic_url).content f.write(pic_bin) f.close() for url_ in url_set: pic_download(url_)
主要仍是在控制chrome滑动窗口的时候须要对滑动次数和页面HTML更新速度进行微调,不然会出现selenium无法获取页面变化的问题。还有就是在获取url的时候最好保持chrome在前台运行(反正不能最小化,可能没法PAGEDOWN?),不然会出问题。
最后想说的就是这只是一个最简陋的爬虫,后续在下载,解析过程当中有不少能够优化的地方,好比并发下载,selenium设置优化等等,这里我就不深刻了。
附上下载后的美图(づ ̄3 ̄)づ╭❤~
http://selenium-python-zh.readthedocs.io/en/latest/locating-elements.html
https://blog.csdn.net/lb245557472/article/details/79978374