基于Python下载网络图片方法汇总代码实例


Posted in Python onJune 24, 2020

本文介绍下载python下载网络图片的方法,包括通过图片url直接下载、通过re/beautifulSoup解析html下载以及对动态网页的处理等。

通过pic_url单个/批量下载

已知图片url,例如http://xyz.com/series-*(1,2..N).jpg,共N张图片,其链接形式较为固定,这样经简单循环,直接通过`f.write(requests.get(url).content)'即可以二进制形式将图片写入。

import os
import requests

def download(file_path, picture_url):
	headers = {
		"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 			(KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE",
		}
	r = requests.get(picture_url, headers=headers)
	with open(file_path, 'wb') as f:
		f.write(r.content)

def main():
	os.makedirs('./pic/', exist_ok=True) # 输出目录

	prefix_url = 'http://xyz.com/series-' # 同一类目下的图片url前缀
	n = 6 # 该类目下的图片总数

	tmp = prefix_url.split('/')[-1]
	for i in range(1, n + 1):
		file_path = './pic/' + tmp + str(i) + '.jpg'
		picture_url = prefix_url + str(i) + '.jpg'
		download(file_path, picture_url)
		

if __name__ == '__main__':
	main()

正则re解析html获取pic_url后下载

在实际操作中,图片url按序排列情况较少,多数情况下用户仅知道网页url,需要对当前网页htnl内容进行解析,获取源码中包含的图片url,常用方法有正则表达式匹配或BeautifulSoup等库解析的方法。

正则re解析的思路是:首先通过 requests.get(url).text 获得当前页面html源码;然后通过正则表达式匹配图片url,如 re.compile(r'[a-zA-z]+://[^\s]*\.jpg') 正则式一般会得到.jpg结尾的url,但其他网站图片url可能会以.png或.webp等结尾,甚至需要其他的正则匹配,为此,读者需要对正则表达式有所了解,强烈推荐 正则表达式30分钟入门教程 ;将前一步得到的图片url加入列表,进行下载。

import os
import re
import requests

def get_html(url):
  headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 ",
    }
  html = requests.get(url, headers=headers).text

  return html

def parse_html(html_text):
  picre = re.compile(r'[a-zA-z]+://[^\s]*\.jpg') # 本正则式得到.jpg结尾的url
  pic_list = re.findall(picre, html_text)

  return pic_list

def download(file_path, pic_url):
  headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 ",
    }
  r = requests.get(pic_url, headers=headers)
  with open(file_path, 'wb') as f:
    f.write(r.content)

def main():
  # 使用时修改url即可
  url = 'http://xyz.com/series'
  html_text = get_html(url)
  pic_list = parse_html(html_text)

  os.makedirs('./pic/', exist_ok=True) # 输出目录
  for pic_url in pic_list:
    file_name = pic_url.split('/')[-1]
    file_path = './pic/' + file_name

    download(file_path, pic_url)
if __name__ == '__main__':
  main()

通过bs4获取pic_url

与正则匹配思路类似,只不过通过Beautiful Soup解析html获得图片url列表,然后依次下载图片。由于各网站html结构有差异,用户需要自行进行适当修改。以下代码是对豆瓣图片的下载。

import os
import time
import requests
from bs4 import BeautifulSoup

def get_html(url):
  headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 			(KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
  }
  html = requests.get(url, headers=headers).text

  return html

def parse_html(html_text):
  soup = BeautifulSoup(html_text, 'html.parser')
  li = soup.find_all('div', attrs={'class':'cover'})

  pic_list = []
  for link in li:
    pic_url = link.find('img').get('src')
    pic_url = pic_url.replace('/m/', '/l/')
    pic_list.append(pic_url)

  return pic_list

def download(file_path, pic_url):
  headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 ",
    }
  r = requests.get(pic_url, headers=headers)
  with open(file_path, 'wb') as f:
    f.write(r.content)

def main():
  '从豆瓣下载石原里美图片,观察发现每页包含30张图片,其url按30递增,如下所示'
  pic_list = []
  for i in range(10):
    url = 'https://movie.douban.com/celebrity/1016930/photos/?type=C&start=' + str(30*i) + '&sortby=like&size=a&subtype=a'
    html_text = get_html(url)
    pic_list += parse_html(html_text)
    
  os.makedirs('./pic/', exist_ok=True) # 输出目录

  for i, pic_url in enumerate(pic_list):
    if i%30 == 0:
      print('正在下载第%s页'%(i/30+1))
    file_name = pic_url.split('/')[-1].split('.')[0] + '.jpg'
    file_path = './pic/' + file_name

    download(file_path, pic_url)

if __name__ == '__main__':
  main()

在下载图片时,发现可以直接访问图片的缩略图url进行下载,但由于豆瓣的反爬策略,直接访问原图url会被服务器拒绝,见下图。解决方法见下一部分。

基于Python下载网络图片方法汇总代码实例

可能遇到的问题

网站反爬虫机制

  • User-Agent:模拟浏览器访问,添加后,服务器会认为是浏览器正常的请求。一般与网页操作相关访问都予以添加。
  • Referer:浏览器以此来判断你从哪一个网页跳转过来。例如在上述豆瓣图片的下载示例中,直接输入网址会被拒绝,但你在网站一步步点击却会在同一地址中得到内容,这就是因为你在一步步访问时是有一个前序跳转地址的,这个地址可以通过“F12”在header中得到,如果找不到的话试一试根目录地址“ movie.douban.com/”,或是前几步的地址”… GitHub仓库'adv_bs4_url.py‘文件 。
  • ip伪装:构建ip池。
  • Cookie伪装:cookie是服务器用来辨别你此时的状态的,每一次向服务器请求cookie都会随之更新。
  • 常用正则式匹配

网页的数据采用异步加载,如js渲染的页面或ajax加载的数据通过get不到完整页面源码。

一种方案是常说的动态爬虫,即采用一些第三方的工具,模拟浏览器的行为加载数据,如Selenium、PhantomJs等。网络上有较多介绍文章,有点麻烦就没有自己写了,后续有需求的话在做吧,不过其他方法已经够用了。

另外可以通过分析页面,找到请求借口,加载页面。其核心就是跟踪页面的交互行为 JS 触发调度,分析出有价值、有意义的核心调用(一般都是通过 JS 发起一个 HTTP 请求),然后我们使用 Python 直接访问逆向到的链接获取价值数据。通过"F12”进行分析,例如对于花瓣网,可以获得其链接为" huaban.com/search/?q=石… request.urlopen(url).read() 读取网页。

基于Python下载网络图片方法汇总代码实例

Pyautogui,鼠标模拟点击的“傻瓜式”流程

本方法仅适用于重复性的工作,而且效率较低,但完全没有被反爬虫策略屏蔽的风险。其核心思想与word中的“宏”类似,就是你告诉计算机一次循环中鼠标分别如何操作,然后让其自动循环。代码简单明了。

import pyautogui
import time

pyautogui.FAILSAFE = True

def get_mouse_positon():
  time.sleep(3) # 此间将鼠标移动到初始位置
  x1, y1 = pyautogui.position()
  print(x1, y1)
  pyautogui.click(x=x1, y=y1, button='right') # 模拟鼠标右键点击,呼出菜单
  time.sleep(5) # 此间将鼠标移动到“save image as...”选项中央
  x2, y2 = pyautogui.position()
  print(x2, y2)
  pyautogui.click(x=x2, y=y2) # 模拟鼠标左键点击,点中“save image as...”
  time.sleep(10) # 此间弹出保存文件弹窗,自行选择保存位置,并将鼠标移至“保存(S)”按钮中央
  x3, y3 = pyautogui.position()
  pyautogui.click(x=x3, y=y3)
  print(x3, y3)


def click_download(N):
  for i in range(N): # 拟下载图片数量
    pyautogui.click(x=517, y=557, duration=0.25, button='right') # 呼出菜单,自行将x/y设置为x1/y1
    time.sleep(1)
    pyautogui.click(x=664, y=773, duration=0.25) # 下载,x/y为x2/y2
    time.sleep(1)
    pyautogui.click(x=745, y=559, duration=0.25) # 保存,x/y为x3/y3
    time.sleep(1)
    pyautogui.click(x=517, y=557, duration=0.25) # 进入下一张图片
    time.sleep(2) # 取决于网络加载速度,自行设置
 if __name__ == "__main__":
  # get_mouse_positon() # 一开始只运行此命令,获取屏幕坐标,后续注释掉该句
  click_download(10)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
寻找网站后台地址的python脚本
Sep 01 Python
python实现根据月份和日期得到星座的方法
Mar 27 Python
Windows下用py2exe将Python程序打包成exe程序的教程
Apr 08 Python
Django卸载之后重新安装的方法
Mar 15 Python
Python正则表达式分组概念与用法详解
Jun 24 Python
Python实现图片转字符画的示例代码
Aug 21 Python
Numpy数组的保存与读取方法
Apr 04 Python
python画一个玫瑰和一个爱心
Aug 18 Python
python3使用QQ邮箱发送邮件
May 20 Python
Python3简单实现串口通信的方法
Jun 12 Python
浅谈Django中view对数据库的调用方法
Jul 18 Python
python 遍历磁盘目录的三种方法
Apr 02 Python
Python 分布式缓存之Reids数据类型操作详解
Jun 24 #Python
PyTorch中model.zero_grad()和optimizer.zero_grad()用法
Jun 24 #Python
Pytorch实现将模型的所有参数的梯度清0
Jun 24 #Python
你需要学会的8个Python列表技巧
Jun 24 #Python
pytorch实现查看当前学习率
Jun 24 #Python
在pytorch中动态调整优化器的学习率方式
Jun 24 #Python
CentOS 7如何实现定时执行python脚本
Jun 24 #Python
You might like
用文本文件制作留言板提示(下)
2006/10/09 PHP
动态为事件添加js代码示例
2009/02/15 Javascript
IE innerHTML,outerHTML所引起的问题
2009/06/04 Javascript
JavaScript实现QueryString获取GET参数的方法
2013/07/02 Javascript
js限制文本框只能输入数字方法小结
2014/06/16 Javascript
js设置cookie过期当前时间减去一秒相当于立即过期
2014/09/04 Javascript
node.js中的fs.fchmod方法使用说明
2014/12/16 Javascript
js实现支持手机滑动切换的轮播图片效果实例
2015/04/29 Javascript
js实现选中复选框文字变色的方法
2015/08/14 Javascript
学习JavaScript设计模式(封装)
2015/11/26 Javascript
Bootstrap实现登录校验表单(带验证码)
2016/06/23 Javascript
RequireJS简易绘图程序开发
2016/10/28 Javascript
Bootstrap风格的zTree右键菜单
2017/02/17 Javascript
LayUI动态设置checkbox不显示的解决方法
2019/09/02 Javascript
javascript将扁平的数据转为树形结构的高效率算法
2020/02/27 Javascript
js实现直播点击飘心效果
2020/08/19 Javascript
[51:22]Fnatic vs IG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python正则表达式匹配ip地址实例
2014/10/09 Python
python脚本实现数据导出excel格式的简单方法(推荐)
2016/12/30 Python
关于Django ForeignKey 反向查询中filter和_set的效率对比详解
2018/12/15 Python
django 自定义过滤器(filter)处理较为复杂的变量方法
2019/08/12 Python
在Python中使用MySQL--PyMySQL的基本使用方法
2019/11/19 Python
css3中背景尺寸background-size详解
2014/09/02 HTML / CSS
浅析CSS3中鲜为人知的属性:-webkit-tap-highlight-color
2017/01/12 HTML / CSS
惠普墨西哥官方商店:HP墨西哥
2016/12/01 全球购物
英国最大的笔记本电脑直销专家:Laptops Direct
2019/07/20 全球购物
如何用SQL语句进行模糊查找
2015/09/25 面试题
什么叫做SQL注入,如何防止
2016/10/04 面试题
求职自我推荐信
2014/06/25 职场文书
信仰心得体会
2014/09/05 职场文书
2014七年级班主任工作总结
2014/12/05 职场文书
2014业务员年终工作总结
2014/12/09 职场文书
2015年公路养护工作总结
2015/05/13 职场文书
刑事附带民事上诉状
2015/05/23 职场文书
解决redis sentinel 频繁主备切换的问题
2021/04/12 Redis
在Java中Collection的一些常用方法总结
2021/06/13 Java/Android