找回密码
 立即注册
首页 业界区 安全 批量下载网络图片或视频

批量下载网络图片或视频

汪之亦 2025-7-5 07:26:53
可复用可组合。

概述

在互联网上浏览时,遇到好看的图片或视频,总想下载保存起来。本文讲述使用Python实现批量下载网络图片或视频的方法。
批量下载网络图片或视频,主要有四步:

  • 生成多个 URL:因为可能需要从多个URL获取图片或视频资源;
  • 抓取网页内容:为析取图片视频资源作准备;
  • 解析URL内容:析取图片视频资源;
  • 下载图片和视频:可调用下载工具。
我们对程序的目标依然是:

  • 可复用:尽量写一次,多处使用。
  • 可组合:能够组合出不同功能的工具。
要做到可复用,就需要尽量把通用的部分抽离出来,做成选项; 要做到可组合,就需要把功能合理地拆分成多个子任务,用不同程序去实现这些子任务。

生成多个URL

多个URL往往是在一个基础URL经过某种变形得到。可以用含有占位符 :p 的模板 t 和参数组成。
gu.py
  1. from typing import List
  2. from urllib.parse import urlparse
  3. import argparse
  4. def generate_urls(base_url: str, m: int, n: int) -> List[str]:
  5.     """
  6.     Generate a series of URLs based on a base URL and transformation rules.
  7.   
  8.     Args:
  9.         base_url (str): The base URL to transform
  10.         m (int): Start number
  11.         n (int): End number (inclusive)
  12.   
  13.     Returns:
  14.         List[str]: List of generated URLs
  15.   
  16.     Examples:
  17.         >>> generate_urls("https://example.com/xxx:pyyy", 1, 3)
  18.         ['https://example.com/xxx1yyy', 'https://example.com/xxx2yyy', 'https://example.com/xxx3yyy']
  19.         >>> generate_urls("https://example.com/page_:p.php", 1, 3)
  20.         ['https://example.com/page_1.php', 'https://example.com/page_2.php', 'https://example.com/page_3.php']
  21.     """
  22.     if not base_url or not isinstance(m, int) or not isinstance(n, int):
  23.         raise ValueError("Invalid input parameters")
  24.   
  25.     if m > n:
  26.         raise ValueError("Start number (m) must be less than or equal to end number (n)")
  27.   
  28.     # Parse the URL to validate it
  29.     parsed_url = urlparse(base_url)
  30.     if not parsed_url.scheme and not base_url.startswith('//'):
  31.         raise ValueError("Invalid URL format")
  32.   
  33.     # Handle the $p pattern
  34.     if ":p" in base_url:
  35.         parts = base_url.split(":p")
  36.         if len(parts) != 2:
  37.             raise ValueError("Invalid URL pattern: should contain exactly one $p")
  38.         prefix, suffix = parts
  39.         return [f"{prefix}{i}{suffix}" for i in range(m, n + 1)]
  40.   
  41.     raise ValueError("URL pattern not supported. Use $p as placeholder for numbers")
  42. def parse_range(range_str: str) -> tuple[int, int]:
  43.     """
  44.     Parse a range string like "1-3" into start and end numbers.
  45.   
  46.     Args:
  47.         range_str (str): Range string (e.g., "1-3")
  48.   
  49.     Returns:
  50.         tuple[int, int]: Start and end numbers
  51.     """
  52.     try:
  53.         start, end = map(int, range_str.split("-"))
  54.         return start, end
  55.     except ValueError:
  56.         raise ValueError("Invalid range format. Use 'start-end' (e.g., '1-3')")
  57. def parse_list(list_str: str) -> List[str]:
  58.     """
  59.     Parse a comma-separated string into a list of values.
  60.   
  61.     Args:
  62.         list_str (str): Comma-separated string (e.g., "1,2,3")
  63.   
  64.     Returns:
  65.         List[str]: List of values
  66.     """
  67.     return [item.strip() for item in list_str.split(",")]
  68. def main():
  69.     parser = argparse.ArgumentParser(description='Generate a series of URLs based on a pattern')
  70.     parser.add_argument('-u', '--url', required=True, help='Base URL with {p} as placeholder')
  71.   
  72.     # Add mutually exclusive group for range or list
  73.     group = parser.add_mutually_exclusive_group(required=True)
  74.     group.add_argument('-r', '--range', help='Range of numbers (e.g., "1-3")')
  75.     group.add_argument('-l', '--list', help='Comma-separated list of values (e.g., "1,2,3")')
  76.   
  77.     args = parser.parse_args()
  78.   
  79.     try:
  80.         if args.range:
  81.             start, end = parse_range(args.range)
  82.             urls = generate_urls(args.url, start, end)
  83.         elif args.list:
  84.             values = parse_list(args.list)
  85.             template = args.url.replace(":p", "{}")
  86.             urls = [template.format(value) for value in values]
  87.       
  88.         for url in urls:
  89.             print(url)
  90.     except ValueError as e:
  91.         print(f"Error: {e}")
  92.         exit(1)
  93. if __name__ == "__main__":
  94.     main()
复制代码
使用方法:
  1. gu -u "https://www.yituyu.com/gallery/:p/index.html" -l "10234,10140"
复制代码
就可以生成 https://www.yituyu.com/gallery/10234/index.html, https://www.yituyu.com/gallery/10140/index.html
或者使用
  1. gu -u "https://www.yituyu.com/gallery/:p/index.html" -r 1-3
复制代码
生成: https://www.yituyu.com/gallery/1/index.html,https://www.yituyu.com/gallery/2/index.html,https://www.yituyu.com/gallery/3/index.html


抓取网页内容

web.py
这里使用了 requests 和 chromedriver 。静态网页可以直接用 requests,动态网页需要用 chromedriver 模拟打开网页。有些网页还需要滚动到最下面加载资源。
  1. import requests
  2. import time
  3. from pytools.common.common import catchExc
  4. from pytools.con.multitasks import IoTaskThreadPool
  5. from selenium import webdriver
  6. from selenium.webdriver.chrome.options import Options
  7. from selenium.webdriver.common.by import By
  8. delayForHttpReq = 0.5 # 500ms
  9. class HTMLGrasper(object):
  10.     def __init__(self, conf):
  11.         '''
  12.         抓取 HTML 网页内容时的配置项
  13.           _async: 是否异步加载网页。 _async = 1 当网页内容是动态生成时,异步加载网页;
  14.           targetIdWhenAsync: 当 _async = 1 指定。
  15.              由于此时会加载到很多噪音内容,需要指定 ID 来精确获取所需的内容部分
  16.           sleepWhenAsync:  当 _async = 1 指定。
  17.              异步加载网页时需要等待的秒数  
  18.         '''
  19.         self._async = conf.get('async', 0)
  20.         self.targetIdWhenAsync = conf.get('targetIdWhenAsync', '')
  21.         self.sleepWhenAsync = conf.get('sleepWhenAsync', 10)
  22.     def batchGrapHtmlContents(self, urls):
  23.         '''
  24.            batch get the html contents of urls
  25.         '''
  26.         grapHtmlPool = IoTaskThreadPool(20)
  27.         return grapHtmlPool.exec(self.getHTMLContent, urls)
  28.     def getHTMLContent(self, url):
  29.         if self._async == 1:
  30.             htmlContent = self.getHTMLContentAsync(url)
  31.             if htmlContent is not None and htmlContent != '':
  32.                 html = '<html><head></head><body>' + htmlContent + '</body></html>'
  33.                 return html
  34.         return self.getHTMLContentFromUrl(url)
  35.     def getHTMLContentAsync(self, url):
  36.         '''
  37.            get html content from dynamic loaed html url
  38.         '''
  39.         chrome_options = Options()
  40.         chrome_options.add_argument('--headless')
  41.         chrome_options.add_argument('--disable-gpu')
  42.         driver = webdriver.Chrome(chrome_options=chrome_options)
  43.         driver.get(url)
  44.         time.sleep(self.sleepWhenAsync)
  45.   
  46.         # 模拟滚动到底部多次以确保加载所有内容
  47.         last_height = driver.execute_script("return document.body.scrollHeight")
  48.         for _ in range(3):  # 最多滚动3次
  49.             # 滚动到底部
  50.             driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
  51.             # 等待加载
  52.             time.sleep(2)
  53.             # 计算新的滚动高度并与上一次比较
  54.             new_height = driver.execute_script("return document.body.scrollHeight")
  55.             if new_height == last_height:
  56.                 break
  57.             last_height = new_height
  58.         try:
  59.             elem = driver.find_element_by_id(self.targetIdWhenAsync)
  60.         except:
  61.             elem = driver.find_element(By.XPATH, '/html/body')
  62.         return elem.get_attribute('innerHTML')   
  63.     def getHTMLContentFromUrl(self, url):
  64.         '''
  65.            get html content from html url
  66.         '''
  67.         r = requests.get(url)
  68.         status = r.status_code
  69.         if status != 200:
  70.             return ''
  71.         return r.text
  72. '''
  73.     # 利用property装饰器将获取name方法转换为获取对象的属性
  74.     @property
  75.     def async(self):
  76.         return self._async
  77.     # 利用property装饰器将设置name方法转换为获取对象的属性
  78.     @async.setter
  79.     def async(self,async):
  80.         self._async = async
  81. '''   
复制代码


析取图片或视频资源

res.py
这里使用了 BeautifulSoup.  网页文件通常是 HTML。因此,需要写一个程序,从 HTML 内容中解析出图片或资源地址。现代web页面通常采用 DIV+CSS+JS 框架。 图片或视频资源,通常是 a, img, video 之类的标签,或者 class 或 id 指定的元素 。再定位到元素的属性,比如 href, src 等。此处需要一点 HTML 和 CSS 知识,还有 jQuery 定位元素的知识。
  1. #!/usr/bin/python3
  2. #_*_encoding:utf-8_*_
  3. import re
  4. import sys
  5. import json
  6. import argparse
  7. from bs4 import BeautifulSoup
  8. from pytools.net.web import HTMLGrasper   
  9. SaveResLinksFile = '/Users/qinshu/joy/reslinks.txt'
  10. serverDomain = ''
  11. def parseArgs():
  12.     description = '''This program is used to batch fetch url resources from specified urls.
  13.                      eg. python3 res.py -u http://xxx.html -r 'img=jpg,png;class=resLink;id=xyz'
  14.                      will search resource links from network urls http://xxx.html  by specified rules
  15.                      img = jpg or png OR class = resLink OR id = xyz [ multiple rules ]
  16.                      python3 tools/res.py -u 'http://tu.heiguang.com/works/show_167480.html' -r 'img=jpg!c'
  17.                      for <img src="https://www.cnblogs.com/xxx.jpg!c"/>
  18.                   '''
  19.     parser = argparse.ArgumentParser(description=description)
  20.     parser.add_argument('-u','--url', nargs='+', help='At least one html urls are required', required=True)
  21.     parser.add_argument('-r','--rulepath', nargs=1, help='rules to search resources. if not given, search a hrefs or img resources in given urls', required=False)
  22.     parser.add_argument('-o','--output', nargs=1, help='Specify the output file to save the links', required=False)
  23.     parser.add_argument('-a','--attribute', nargs=1, help='Extract specified attribute values from matched elements', required=False)
  24.     args = parser.parse_args()
  25.     init_urls = args.url
  26.     rulepath = args.rulepath
  27.     output_file = args.output[0] if args.output else SaveResLinksFile
  28.     return (init_urls, rulepath, output_file, args.attribute[0] if hasattr(args, 'attribute') and args.attribute else None)
  29. def getAbsLink(serverDomain, link):
  30.     try:
  31.         link_content = link
  32.         if link_content.startswith('//'):
  33.             link_content = 'https:' + link_content
  34.         if link_content.startswith('/'):
  35.             link_content = serverDomain + link_content
  36.         return link_content
  37.     except:
  38.         return ''
  39. def batchGetResTrueLink(resLinks):
  40.     return filter(lambda x: x != '', resLinks)
  41. resTags = set(['img', 'video', 'a', 'div'])
  42. def findWantedLinks(htmlcontent, rule, attribute):
  43.     '''
  44.        find html links or res links from html by rule.
  45.        sub rules such as:
  46.           (1) a link with id=[value1,value2,...]
  47.           (2) a link with class=[value1,value2,...]
  48.           (3) res with src=xxx.jpg|png|mp4|...
  49.        a rule is map containing sub rule such as:
  50.           { 'id': [id1, id2, ..., idn] } or
  51.           { 'class': [c1, c2, ..., cn] } or
  52.           { 'img': ['jpg', 'png', ... ]} or
  53.           { 'video': ['mp4', ...]}
  54.     '''
  55.     #print("html===\n"+htmlcontent+"\n===End")
  56.     #print("rule===\n"+str(rule)+"\n===End")
  57.     soup = BeautifulSoup(htmlcontent, "lxml")
  58.     all_links = []
  59.     attribute_links = []
  60.     for (key, values) in rule.items():
  61.         if key == 'id':
  62.             for id in values:
  63.                 link_soups = soup.find_all('a', id=id)
  64.         elif key == 'class':
  65.             for cls in values:
  66.                 link_soups = findLinkSoups(soup, ['a', 'img', 'div'], cls)   
  67.         elif key in resTags:
  68.             link_soups = []
  69.             for resSuffix in values:
  70.                 if resSuffix != "":
  71.                     link_soups.extend(soup.find_all(key, src=re.compile(resSuffix)))
  72.                 else:
  73.                     link_soups = soup.find_all(key)
  74.     attribute_links.extend([link.get(attribute) for link in link_soups if link.get(attribute)])
  75.     all_links.extend(attribute_links)
  76.     return all_links
  77. def findLinkSoups(soup, tags, cls):
  78.     all_link_soups = []
  79.     if len(tags) == 0:
  80.         all_link_soups.extend(soup.find_all("a", class_=cls))  
  81.     else:
  82.         for tag in tags:
  83.             if cls != "":
  84.                 link_soups = soup.find_all(tag, class_=cls)
  85.             else:
  86.                 link_soups = soup.find_all(tag)
  87.             all_link_soups.extend(link_soups)
  88.     return all_link_soups
  89. def batchGetLinks(urls, rules, output_file, attribute=None):
  90.     conf = {"async":1, "targetIdWhenAsync": "page-fav", "sleepWhenAsync": 10}
  91.     grasper = HTMLGrasper(conf)
  92.     htmlcontentList = grasper.batchGrapHtmlContents(urls)
  93.     allLinks = []
  94.     for htmlcontent in htmlcontentList:
  95.         for rule in rules:
  96.             links = findWantedLinks(htmlcontent, rule, attribute)
  97.             allLinks.extend(links)
  98.   
  99.     with open(output_file, 'w') as f:
  100.         for link in allLinks:
  101.             print(link)
  102.             f.write(link + "\n")
  103. def parseRulesParam(rulesParam):
  104.     '''
  105.        parse rules params to rules json
  106.        eg. img=jpg,png;class=resLink;id=xyz to
  107.            [{"img":["jpg","png"], "class":["resLink"], "id":["xyz"]}]
  108.     '''
  109.     defaultRules = [{'img': ['jpg','png','jpeg']},{"class":"*"}]
  110.     if rulesParam:
  111.         try:
  112.             rules = []
  113.             rulesStrArr = rulesParam[0].split(";")
  114.             for ruleStr in rulesStrArr:
  115.                 ruleArr = ruleStr.split("=")
  116.                 key = ruleArr[0]
  117.                 value = ruleArr[1].split(",")
  118.                 rules.append({key: value})
  119.             return rules
  120.         except ValueError as e:
  121.             print('Param Error: invalid rulepath %s %s' % (rulepathjson, e))
  122.             sys.exit(1)
  123.     return defaultRules
  124. def testBatchGetLinks():
  125.     urls = ['http://dp.pconline.com.cn/list/all_t145.html']
  126.     rules = [{"img":["jpg"], "video":["mp4"]}]
  127.     batchGetLinks(urls, rules, SaveResLinksFile)
  128. if __name__ == '__main__':
  129.     #testBatchGetLinks()
  130.     (init_urls, rulesParam, output_file, attribute) = parseArgs()
  131.     if not output_file:
  132.         output_file = SaveResLinksFile
  133.     # print('init urls: %s' % "\n".join(init_urls))
  134.     rulepath = parseRulesParam(rulesParam)
  135.     # print('rulepath: %s\n' % (rulepath))
  136.     batchGetLinks(init_urls, rulepath, output_file, attribute)
复制代码
怎么找到对应的资源地址?右键-控制台,鼠标点击最左边那个箭头指向的小方框,然后在点击网页元素,就会定位到网页元素,下面图片资源地址就是 img 的 data-src 属性 或者 src 属性。 不过这里 src 属性是需要滚动到最后才能展示所有的,但 data-src 是直接加载的。如果要省时,就可以用 data-src 属性。好处是快,不足是不通用。视频地址类似。
2.png

将图片资源URL下载到 ~/Downloads/links5.txt,整个命令是:
  1. gu -u "https://www.yituyu.com/gallery/:p/index.html" -l "9174,9170" | xargs -I {} python3 ~/tools/pytools/pytools/tools/res.py -u {} -r "class=lazy" -a "data-src" -o ~/Downloads/links5.txt
复制代码
下载图片或视频

dw.py
  1. #!/usr/bin/env python3
  2. import subprocess
  3. import shlex
  4. from pathlib import Path
  5. from typing import Optional, Union, List
  6. import time
  7. import requests
  8. import argparse
  9. default_save_path = "/Users/qinshu/Downloads"
  10. def download(url: str, output_dir: Union[str, Path]) -> Optional[Path]:
  11.     output_dir = Path(output_dir)
  12.     if url.endswith(".jpg") or url.endswith(".png"):
  13.         download_image(url, output_dir / Path(url).name)
  14.     else:
  15.         download_video(url, output_dir)  
  16.         return output_dir / Path(url).name
  17.     return None
  18. def download_image(url: str, output_file: Union[str, Path]) -> None:
  19.     try:
  20.         # 发送 HTTP GET 请求获取图片
  21.         response = requests.get(url, stream=True)
  22.         response.raise_for_status()  # 检查请求是否成功
  23.         # 以二进制写入模式保存图片
  24.         with open(output_file, 'wb') as f:
  25.             for chunk in response.iter_content(1024):
  26.                 f.write(chunk)
  27.       
  28.         print(f"图片已保存至: {output_file}")
  29.     except requests.exceptions.RequestException as e:
  30.         print(f"下载失败: {e}")
  31.     except Exception as e:
  32.         print(f"发生错误: {e}")
  33. def download_video(
  34.     video_url: str,
  35.     output_dir: Union[str, Path] = Path.cwd(),
  36.     timeout: int = 3600,  # 1小时超时
  37.     retries: int = 1,
  38.     verbose: bool = True
  39. ) -> Optional[Path]:
  40.     """
  41.     使用 y 命令下载视频
  42.   
  43.     参数:
  44.         video_url: 视频URL (e.g. "https://www.bilibili.com/video/BV1xx411x7xx")
  45.         output_dir: 输出目录 (默认当前目录)
  46.         timeout: 超时时间(秒)
  47.         retries: 重试次数
  48.         verbose: 显示下载进度
  49.   
  50.     返回:
  51.         成功时返回下载的视频路径,失败返回None
  52.     """
  53.     if video_url == "":
  54.         return None
  55.     output_dir = Path(output_dir)
  56.     output_dir.mkdir(parents=True, exist_ok=True)
  57.   
  58.     cmd = f"y {shlex.quote(video_url)}"
  59.     if verbose:
  60.         print(f"开始下载: {video_url}")
  61.         print(f"保存到: {output_dir.resolve()}")
  62.         print(f"执行命令: {cmd}")
  63.   
  64.     for attempt in range(1, retries + 1):
  65.         try:
  66.             start_time = time.time()
  67.          
  68.             # 使用Popen实现实时输出
  69.             process = subprocess.Popen(
  70.                 cmd,
  71.                 shell=True,
  72.                 cwd=str(output_dir),
  73.                 stdout=subprocess.PIPE,
  74.                 stderr=subprocess.STDOUT,
  75.                 universal_newlines=True,
  76.                 bufsize=1
  77.             )
  78.          
  79.             # 实时打印输出
  80.             while True:
  81.                 output = process.stdout.readline()
  82.                 if output == '' and process.poll() is not None:
  83.                     break
  84.                 if output and verbose:
  85.                     print(output.strip())
  86.               
  87.                 # 检查超时
  88.                 if time.time() - start_time > timeout:
  89.                     process.terminate()
  90.                     raise subprocess.TimeoutExpired(cmd, timeout)
  91.          
  92.             # 检查返回码
  93.             if process.returncode == 0:
  94.                 if verbose:
  95.                     print(f"下载成功 (尝试 {attempt}/{retries})")
  96.                 return _find_downloaded_file(output_dir, video_url)
  97.             else:
  98.                 raise subprocess.CalledProcessError(process.returncode, cmd)
  99.               
  100.         except (subprocess.TimeoutExpired, subprocess.CalledProcessError) as e:
  101.             if attempt < retries:
  102.                 wait_time = min(attempt * 10, 60)  # 指数退避
  103.                 if verbose:
  104.                     print(f"尝试 {attempt}/{retries} 失败,{wait_time}秒后重试...")
  105.                     print(f"错误: {str(e)}")
  106.                 time.sleep(wait_time)
  107.             else:
  108.                 if verbose:
  109.                     print(f"下载失败: {str(e)}")
  110.                 return None
  111. def _find_downloaded_file(directory: Path, video_url: str) -> Optional[Path]:
  112.     """尝试自动查找下载的文件"""
  113.     # 这里可以根据实际y命令的输出文件名模式进行调整
  114.     # 示例:查找最近修改的视频文件
  115.     video_files = sorted(
  116.         directory.glob("*.mp4"),
  117.         key=lambda f: f.stat().st_mtime,
  118.         reverse=True
  119.     )
  120.     return video_files[0] if video_files else None
  121. def read_urls_from_file(file_path: Union[str, Path]) -> List[str]:
  122.     with open(file_path, 'r') as f:
  123.         return [line.strip() for line in f if line.strip()]
  124. def main():
  125.     parser = argparse.ArgumentParser(description="下载工具:支持从URL或文件下载视频和图片")
  126.     parser.add_argument("-u", "--url", help="单个下载URL")
  127.     parser.add_argument("-f", "--file", help="包含多个URL的文件路径(每行一个URL)")
  128.     parser.add_argument("-o", "--output", default=".", help="输出目录路径(默认为当前目录)")
  129.     args = parser.parse_args()
  130.     if not args.url and not args.file:
  131.         parser.error("必须提供 -u 或 -f 参数")
  132.     if not args.output:
  133.         output_dir = default_save_path
  134.     else:   
  135.         output_dir = Path(args.output)
  136.     output_dir.mkdir(parents=True, exist_ok=True)
  137.     urls = []
  138.     if args.url:
  139.         urls.append(args.url)
  140.     if args.file:
  141.         urls.extend(read_urls_from_file(args.file))
  142.     for url in urls:
  143.         print(f"处理URL: {url}")
  144.         result = download(url, output_dir)
  145.         if result:
  146.             print(f"下载完成: {result}")
  147.         else:
  148.             print(f"下载失败: {url}")
  149. if __name__ == "__main__":
  150.     main()
复制代码
注册工具

要想运行工具,就需要 python /path/to/python_file.py ,每次写全路径挺麻烦的。可以写一个shell 脚本,将写的 python 工具注册到 ~/.zshrc ,然后每次 source ~/.zshrc 即可。
  1. #!/bin/bash
  2. # Get the absolute path of the tools directory
  3. TOOLS_DIR="/Users/qinshu/tools/pytools/pytools/tools"
  4. # Add a comment to mark the beginning of our tools section
  5. echo -e "\n# === Python Tools Aliases ===" >> ~/.zshrc
  6. # Loop through all Python files in the tools directory
  7. for file in "$TOOLS_DIR"/*.py; do
  8.     if [ -f "$file" ]; then
  9.         # Get just the filename without extension
  10.         filename=$(basename "$file" .py)
  11.       
  12.         # Skip .DS_Store and any other hidden files
  13.         if [[ $filename != .* ]]; then
  14.             # Create the alias command
  15.             alias_cmd="alias $filename="python3 $file""
  16.          
  17.             # Check if this alias already exists in .zshrc
  18.             if ! grep -q "alias $filename=" ~/.zshrc; then
  19.                 echo "$alias_cmd" >> ~/.zshrc
  20.                 echo "Added alias for: $filename"
  21.             else
  22.                 echo "Alias already exists for: $filename"
  23.             fi
  24.         fi
  25.     fi
  26. done
  27. echo "All Python tools have been registered in ~/.zshrc"
  28. echo "Please run 'source ~/.zshrc' to apply the changes"
复制代码
这里实际上就是生成了一系列 alias:
  1. alias gu="python3 /Users/qinshu/tools/pytools/pytools/tools/gu.py"
  2. alias res="python3 /Users/qinshu/tools/pytools/pytools/tools/res.py"
  3. alias dw="python3 /Users/qinshu/tools/pytools/pytools/tools/dw.py"
复制代码
这样就可以直接用
  1. gu -u 'https://xxx' -l 1-3
复制代码
从该网站批量下载图片的整个命令合起来是:
  1. gu -u "https://www.yituyu.com/gallery/:p/index.html" -l "9174,9170" | xargs -I {} python3 ~/tools/pytools/pytools/tools/res.py -u {} -r "class=lazy" -a "data-src" -o ~/Downloads/links5.txt  && dw -f -o ~/Downloads/links5.txt
复制代码
虽然繁琐了一点,但是胜在通用。


小结

本文讲解了批量下载网络图片或视频的方法,包括四个主要步骤:生成多个URL、抓取网页内容、析取资源地址、下载资源。每个步骤既独立又承上启下,因此做到了可组合。要做到通用,需要掌握一些基本编程知识。当你了解其中一些原理时,就能获得更强的能力,而不仅仅局限于 GUI。


来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除

相关推荐

您需要登录后才可以回帖 登录 | 立即注册