完成这个操作主要还是用到了 BeautifulSoup 和 requests 这两个库来提取图片中的地址信息,再加上用到了多进程 + 简单的正则表达式的知识,不是很复杂。加上了一个简单的小功能显示程序运行了多长时间来完成下载图片的操作。
这里的链接必须要用以下的形式:https://www.zhihu.com/question/?????????/answer/?????????
就是要有 answer 后面的部分。下载某个问题下的所有回答的所有图片暂时还未实现。有思路的还请留言。
参考:
Quickstart — Requests 2.18.3 documentation
Beautiful Soup 4.4.0 文档 — beautifulsoup 4.4.0 文档
多进程 - 廖雪峰的官方网站
代码如下:
#!/usr/bin/python3
#! -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
from multiprocessing import Pool
import requests,re,time
session = requests.Session()
# 使用手机版的UA ,获取到的页面比电脑版 UA 更容易操作
session.headers.update({'User-Agent':'Mozilla/5.0 (Linux; U; Android 4.4.4; Nexus 5 Build/KTU84P) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'})
root_url = 'https://www.zhihu.com/question/51504667/answer/137780139'
def download_save_img(url): #根据地址下载并保存图片
pattern = re.compile('https://pic([0-9]{1}).zhimg.com/([0-9a-zA-z_.-]+)')
#知乎图片链接的正则表达式
for val in url:
#print(val)
#hint: 如果只输出了四个地址,请检查接下来的四行内有无错误
res = pattern.findall(val)
img = session.get(url=val,timeout=5)
with open(res[0][1],'wb')as file:
file.write(img.content)
#保存图片,这里可以对 img 的状态进行考虑再进行后续操作
if __name__ == '__main__':
start = time.time() # 开始时间
s = session.get(root_url)
if s.status_code == 200:
soup = BeautifulSoup(s.content,'lxml')
answer = soup.find('div',attrs={'class':'AnswerItem-content'})
image = answer.find_all('img',attrs={'class':'origin_image zh-lightbox-thumb lazy'})
# 显示图片数量
print('%d image(s) found in %s' % (len(image),root_url))
#显示回答的内容,显示效果不好暂时隐藏
#text = answer.find('div',attrs={'class':'RichText'})
#print(text.getText().replace(' ',''))
result = []
for val in image:
result.append(val['data-actualsrc'])
p = Pool()
for i in range(4):
p.apply_async(download_save_img,args=(result[i::4],))
p.close() #停止添加新进程
p.join() #等待所有进程执行
end = time.time() # 结束时间
print('finish in %.2f second(s)'%(end-start)) # 输出结果
#with open('res.html','w') as file:
#file.write(str(soup.prettify()))
来自个人 Python 文集