上次说了要爬知乎的图片,于是花了一下午的时间去完成这件事,发现暂时接触到的爬虫总是逃脱不了一个规律:

  • 模拟登陆
  • 获取真实网页HTML源代码
  • 解析获取到的网页源代码
  • 获取想要的资源(下载到某个文件夹或者输出到表格中整合起来)

也许和我说的有一些出入,应该是刚学这个东西的原因,接下来还想研究一下多线程爬虫、添加代理、爬取海量数据并整合成图标形式,先把能做的做了。

因为是在上一次的基础上进行的,所以没有看上一篇文章的可以先看一下,这里用到的工具跟之前一样:

  • win7 64位 旗舰版
  • Python 3.5 64-bit
  • PyCharm

这里模拟登陆是跟之前一样的代码,直接贴就是:

logn_url = 'http://www.zhihu.com/#signin'session = requests.session()headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36',
}content = session.get(logn_url, headers=headers).content
soup = BeautifulSoup(content, 'html.parser')def getxsrf():return soup.find('input', attrs={'name': "_xsrf"})['value']# 获取验证码
def get_captcha():t = str(int(time.time() * 1000))captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + "&type=login"r = session.get(captcha_url, headers=headers)with open('captcha.jpg', 'wb') as f:f.write(r.content)f.close()# 用pillow 的 Image 显示验证码# 如果没有安装 pillow 到源代码所在的目录去找到验证码然后手动输入try:im = Image.open('captcha.jpg')im.show()im.close()except:print(u'请到 %s 目录找到captcha.jpg 手动输入' % os.path.abspath('captcha.jpg'))captcha = input("please input the captcha\n>")return captchadef isLogin():# 通过查看用户个人信息来判断是否已经登录url = "https://www.zhihu.com/settings/profile"login_code = session.get(url, allow_redirects=False).status_codeif int(x=login_code) == 200:return Trueelse:return Falsedef login(secret, account):# 通过输入的用户名判断是否是手机号if re.match(r"^1\d{10}$", account):print("手机号登录 \n")post_url = 'http://www.zhihu.com/login/phone_num'postdata = {'_xsrf': getxsrf(),'password': secret,'remember_me': 'true','phone_num': account,}else:print("邮箱登录 \n")post_url = 'http://www.zhihu.com/login/email'postdata = {'_xsrf': getxsrf(),'password': secret,'remember_me': 'true','email': account,}try:# 不需要验证码直接登录成功login_page = session.post(post_url, data=postdata, headers=headers)login_code = login_page.textprint(login_page.status)print(login_code)except:# 需要输入验证码后才能登录成功postdata["captcha"] = get_captcha()login_page = session.post(post_url, data=postdata, headers=headers)login_code = eval(login_page.text)print(login_code['msg'])

这里的代码来自GitHub上的fuck-login项目,在此表示感谢,我在原始代码上进行了改进,原始代码是适配了Python2.x和Python3.x,但是我学的是Python3.x所以去掉了一些我没用过的模块,也就是说我改进了后的代码是适用于Python3.x的。

下面就是准备获取图片了,先找一个目标,最近有一个问题很火:

长得好看,但没有男朋友是怎样的体验

还记得我列出来的步骤么,模拟登陆之后是获取真实的网页源代码,什么叫真实的,这个问题问得好,你没发现知乎很喜欢用动态加载技术么,也就是说,你看到的只是表象,这里也一样。


插播一下:这篇文章首发http://blog.csdn.net/wei_smile,同步发表在简书跟个人博客,无耻的code xiu网站经常盗用我的文章不署名,盗版可耻,抄袭下流~~

来,我们先点赞数最高的妹子上传的图片:

咳咳咳,好像跑偏了,我们的目标是星辰大海,正确的做法是鼠标右键查看网页源代码:

是不是看到了很多图片链接,当然我们要找.jpg、.jpeg、.png后缀的:

<img data-rawwidth="1632" data-rawheight="2040" src="//zhstatic.zhihu.com/assets/zhihu/ztext/whitedot.jpg" class="origin_image zh-lightbox-thumb lazy" width="1632" data-original="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_r.jpg" data-actualsrc="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_b.jpg">

这里有两个:data-originaldata-actualsrc,实际查看的图片是data-original的图片比data-actualsrc的大,下载下来也是如此,但是因为是使用正则去匹配规则,而data-original有多项,上面代码只是贴出来的一部分,实际匹配的结果类似这样:

data-actualsrc

data-actualsrc="https://pic2.zhimg.com/be7600989233bdf438e5ba23f2cdb685_b.jpg">
data-actualsrc="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_b.jpg">

data-original

data-original="https://pic2.zhimg.com/be7600989233bdf438e5ba23f2cdb685_r.jpg">
data-original="https://pic2.zhimg.com/be7600989233bdf438e5ba23f2cdb685_r.jpg" data-actualsrc="https://pic2.zhimg.com/be7600989233bdf438e5ba23f2cdb685_b.jpg">
data-original="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_r.jpg">
data-original="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_r.jpg" data-actualsrc="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_b.jpg">
data-original="https://pic2.zhimg.com/0930549116d22ffce22e98c32683d621_r.jpg">

这是在同一段网页源码测试下的结果,匹配后一种会得到多个相同的url地址,解析起来也更麻烦,这也跟正则写的简单有关系,有兴趣的可以到时候自己修改一下正则表达式,这样下下来的图片也更高清的多。

分析了正则,下面要获取所有的图片该分析Chrome开发者面板的Post数据,因为知乎默认只显示部分回答,我们可以不断往下拉,直到看到这个:

点击的时候注意观察开发者面板:

简直完美,传递的数据:

method:next
params:{"url_token":37709992,"pagesize":10,"offset":30}

很眼熟,url_token就是问题后面那串数字:

https://www.zhihu.com/question/37709992

pagesize是固定的10,最后一个offset偏移量同样很好理解,这里显示10应该说的就是默认显示的10个答案,后面还查看到如下数据:

method:next
params:{"url_token":37709992,"pagesize":10,"offset":20}
method:next
params:{"url_token":37709992,"pagesize":10,"offset":30}

也就是说我们在浏览器上每翻过10个答案浏览器就会向服务器发送Post请求在加载十个答案,恩差不多可以开始写代码了。

模拟登陆之后的操作是找到Post的真实地址模拟浏览器向服务器发送请求:

    url = 'https://www.zhihu.com/node/QuestionAnswerListV2'header = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36','Referer': 'https://www.zhihu.com/question/37709992','Origin': 'https://www.zhihu.com','Accept-Encoding': 'gzip, deflate, br',}data = {'method': 'next','params': '{"url_token":' + str(37709992) + ',"pagesize": "10",' + \'"offset":' + str(offset) + "}",'_xsrf': getxsrf(),}

注意

发送Post请求时候请加上'_xsrf': getxsrf()这一行,否则的话返回的只会是404 Forbidden,应该是做了防伪登陆的缘故

然后是写正则,这里发现图片都是被包含在这里面:

<div class="zm-editable-content clearfix">
...
...
</div>

所以先匹配到这一大串内容:

        pattern = re.compile('<a class="author-link".*?<span title=.*?<div class="zh-summary.*?' +'<div class="zm-editable-content.*?>(.*?)</div>', re.S)

然后在匹配data-actualsrc里面的图片链接:

pattern = re.compile('data-actualsrc="(.*?)">', re.S)

还有一点要注意的是我们请求之后返回来的是json格式的数据,所以这里还要用到json模块:

 question = session.post(url, headers=header, data=data)dic = json.loads(question.content.decode('ISO-8859-1'))li = dic['msg'][0]

然后对其进行解析:

# 这里使用的是第一个正则表达式
items = re.findall(pattern, li)
# 接下来
items = re.findall(pattern, li)
# 存储图片链接
imagesurl = []
pattern = re.compile('data-actualsrc="(.*?)">', re.S)
for item in items:urls = re.findall(pattern, item)imagesurl.extend(urls)

执行下载操作:

# 存放图片的地址
PWD = "D:/work/python/zhihu/"for url in imagesurl:myurl = urlfilename = PWD + str(count) + '.jpg'if os.path.isfile(filename):print("文件存在:", filename)count += 1continueelse:# 执行下载操作的方法downpic(filename, myurl)count += 1photoNum += 1print("一共下载了{0} 张照片".format(photoNum))if not os.path.exists(PWD):os.makedirs(PWD)# 递归调用change(offset, count, photoNum)# downpic方法源码
def downpic(filename, url):print("正在下载 " + url)try:r = requests.get(url, stream=True)with open(filename, 'wb') as fd:for chunk in r.iter_content():fd.write(chunk)except Exception as e:print("下载失败了", e)

运行结果

这只是一部分,我之前下了四五百张还在下~当然这是后话,感觉现在写的东西都很简单,希望下一次能写出难一点的东西出来。

这里正则部分参考了这里:

通过Python爬虫爬取知乎某个问题下的图片

最后是源码

源码中注释部分只能下载前十个答案里包含的图片的方法,还有一些想法未完成,本来是想打印一下正在下载哪个答主的回答,然后把图片分别保存到相应的单独文件夹,实现起来有点麻烦就没去搞,仅供参考。

亲测如果需要下载另一个问题的答案,只需要在:

 data = {'method': 'next','params': '{"url_token":' + str(37709992) + ',"pagesize": "10",' + \'"offset":' + str(offset) + "}",'_xsrf': getxsrf(),}

更换那串数字就行,就好比这样的形式:

https://www.zhihu.com/question/48720845

但是这种形式的把数字换上去不起效:

https://www.zhihu.com/question/49078894#answer-41776282

这个好像是知乎热门问答的链接形式,暂时没有深究

人生苦短,我用Python--分分钟下载知乎美图给你看相关推荐

  1. 人生苦短我用python壁纸_人生苦短我用Python分分钟下载知乎美图给你看

    为什么说"人生苦短,我用python"? 为什么说人生苦短我用python Question 1 Python是什么 2 人们为什么用Python 3 Python是脚本语言吗 P ...

  2. python 批量下载知网(CNKI)论文

    1.目的: 朋友找我去知网帮他下载点相关论文,发现老是要去点击文章.点击下载,显得很麻烦,百度一下,别人的方法太复杂,所以自己写了一个python脚本自动下载知网论文. 2.前期准备 1)安装pyth ...

  3. python画美图_用python做个街拍美图手册

    今天分享一篇在家就能养眼的技能,用python爬取街拍美女高清大图,然后批量插入word中,制作街拍美图手册,闲的时候就能拿出来养养眼.本文涉及知识主要包括Ajax动态加载网页爬取.requests保 ...

  4. 教你用python做个街拍美图手册

    今天分享一篇在家就能养眼的技能,用python爬取街拍美女高清大图,然后批量插入word中,制作街拍美图手册,闲的时候就能拿出来养养眼. 本文涉及知识主要包括Ajax动态加载网页爬取.requests ...

  5. 自学Python九 爬虫实战二(美图福利)

    作为一个新世纪有思想有文化有道德时刻准备着的屌丝男青年,在现在这样一个社会中,心疼我大慢播抵制大百度的前提下,没事儿上上网逛逛YY看看斗鱼翻翻美女图片那是必不可少的,可是美图虽多翻页费劲!今天我们就搞 ...

  6. Python爬取张家界风景美图

    这里利用周末的时间复习了一下关于爬虫的一些基本知识,分别是requests, BeautifulSoup库的基本知识: 如果还有不会的可以去看看这些内容: 参考 requests库 requests实 ...

  7. Web自动化神器,批量下载小姐姐美图,可直接导入使用

    大家好,我是小碗汤,今天为大家分享一款前端自动化操作神器: Automa 文末有流程图获取方式,可自行导入享用. Automa介绍 它是一款 Chrome 插件,即使你不会写代码,也能按照自己的需求, ...

  8. python 批量下载知网(cnki)论文_Python 实现 CNKI批量下载 和FireFox Extension 入门学习笔记...

    ‍Python 实现 CNKI批量下载 和FireFox Extension 入门学习笔记‍ 由于需要也是为了督促自己学习新的东西,我原本想要尝试着写一个爬虫程序,能够在cnki上自动得将论文进行批量 ...

  9. python 批量下载知网(cnki)论文_Python 实现 CNKI批量下载 和FireFox Extension 入门学习笔记 顶...

    ‍Python 实现 CNKI批量下载 和FireFox Extension 入门学习笔记‍ 由于需要也是为了督促自己学习新的东西,我原本想要尝试着写一个爬虫程序,能够在cnki上自动得将论文进行批量 ...

最新文章

  1. isis协议_ISIS基础知识介绍
  2. C#教程6:流控制语句
  3. 【干货】TensorFlow 2.0官方风格与设计模式指南(附示例代码)
  4. win10+anaconda3安装tensorflow-gpu和pytorch-gpu版
  5. Linux下精准踢掉登录用户-pkill命令
  6. 方舟服务器维护驯龙,方舟生存进化新手图文攻略 最详细的驯龙教程方法
  7. java——获取一个应用程序运行的次数,如果超过5次,给出使用次数已到请注册的提示,并不要再运行程序
  8. mysql 用数据库存储视频文件_如何用SQL数据库存放视频
  9. mysql数据库数字类型_Mysql 数据库数值类型详解
  10. python安装找不到.log的文件_python – logger找不到文件
  11. 20210701:随机信号的功率谱估计相关算法的实现
  12. Swagger生成WebAPI文档
  13. Oracle创建新用户一系列操作模板
  14. 定时刷新页面 html,js实现定时刷新页面的代码
  15. 无法打开计算机的组策略,本地组策略编辑器打不开?Win7本地组策略编辑器无法打开的解决方法...
  16. 笔记本电脑里计算机未响应,浅析笔记本win7系统下Word程序总是未响应的原因及解决办法【图文】...
  17. 数量乘单价秋金额的计算机公式,在电子表格中数量乘以单价等于金额用什么样的公式啊?怎么算呢?...
  18. php 0x80070005,FastCGI Error Number: 5 (0x80070005)解决方法
  19. 微博第三方+海外国际版+V2EX第三方
  20. backgroundLinearGradient线性渐变制作折角效果

热门文章

  1. Google Android Pie,谷歌安卓9.0正式版发布,定名Android Pie
  2. 蚂蚁分类信息系统 列表显示标签名称和值
  3. mysql 5.7 exe_mysql 5.7 版本 windows 安装
  4. 随需环绕,浸享影院,飞利浦Fidelio全景声影院 B97震撼上市
  5. DEDECMS全站伪静态详细教程(首页、列表、文章页)
  6. idea 设置本地动态库
  7. DrawerLayout禁用侧边滑动
  8. 2014 android 机型排行,2014年国产智能手机排名 最好的20款智能手机【详解】
  9. python kafka库选择_【linux】安装python依赖库confluent_kafka
  10. 直接发个官方自带的MarkDown编辑教程