行业资讯
影刀RPA 网页图片批量下载:URL提取与保存
影刀RPA 网页图片批量下载URL提取与保存作者林焱什么情况用什么需要把网页上的图片批量下载到本地——商品图片、文章配图、证件照片、设计素材。在影刀RPA里需要先提取图片URL再批量下载保存还要处理重命名、去重、懒加载等问题。适用场景电商商品图片批量保存、新闻配图下载、网页素材采集、图片素材库构建。怎么做拼多多店群自动化报活动上架提取图片URLfrombs4importBeautifulSoupimportrequestsdefextract_image_urls(url):提取网页所有图片URLheaders{User-Agent:Mozilla/5.0...}responserequests.get(url,headersheaders,timeout10)soupBeautifulSoup(response.text,html.parser)image_urls[]forimginsoup.find_all(img):# 优先取data-src懒加载真实地址src(img.get(data-src)orimg.get(data-original)orimg.get(src,))ifnotsrcorsrc.startswith(data:):continue# 跳过base64图片# 处理相对路径ifsrc.startswith(//):srchttps:srcelifsrc.startswith(/):srcrequests.compat.urljoin(url,src)elifnotsrc.startswith(http):srcrequests.compat.urljoin(url,src)# 去重ifsrcnotinimage_urls:image_urls.append(src)returnimage_urls# 使用urlsextract_image_urls(https://example.com/products)print(f共找到{len(urls)}张图片)批量下载图片importosimporttimefromdatetimeimportdatetimedefbatch_download_images(image_urls,save_dir,naming_ruleindex): 批量下载图片 naming_rule: index序号, md5URL的MD5, original原文件名 os.makedirs(save_dir,exist_okTrue)results[]fori,urlinenumerate(image_urls,1):try:# 生成文件名ifnaming_ruleindex:extget_extension_from_url(url)filenamefimage_{i:04d}{ext}elifnaming_rulemd5:importhashlib extget_extension_from_url(url)filenamehashlib.md5(url.encode()).hexdigest()extelifnaming_ruleoriginal:filenameurl.split(/)[-1].split(?)[0]ifnotfilename:filenamefimage_{i}{get_extension_from_url(url)}filepathos.path.join(save_dir,filename)# 下载headers{User-Agent:Mozilla/5.0...}responserequests.get(url,headersheaders,timeout15,streamTrue)ifresponse.status_code200:withopen(filepath,wb)asf:forchunkinresponse.iter_content(8192):f.write(chunk)file_sizeos.path.getsize(filepath)results.append({url:url,filename:filename,path:filepath,size:file_size,status:成功})print(f[{i}/{len(image_urls)}]{filename}({file_size//1024}KB))else:results.append({url:url,status:fHTTP{response.status_code}})exceptExceptionase:results.append({url:url,status:f错误:{e}})time.sleep(0.5)# 延迟避免封IPreturnresultsdefget_extension_from_url(url):从URL获取文件扩展名importos pathurl.split(?)[0]# 去掉参数extos.path.splitext(path)[1].lower()ifextin(.jpg,.jpeg,.png,.gif,.webp,.bmp,.svg):returnextreturn.jpg# 默认jpg影刀RPA完整流程【设置变量】 page_url https://example.com/products save_dir rC:\Images\产品图片 【打开网页】page_url 【等待元素出现】→ .product-image 【执行Python代码】 # 获取页面HTML html yd_var[page_source] # 提取图片URL from bs4 import BeautifulSoup soup BeautifulSoup(html, html.parser) urls [] for img in soup.select(.product-image img): src img.get(data-src) or img.get(src, ) if src and not src.startswith(data:): if src.startswith(//): src https: src urls.append(src) yd_var[image_urls] urls 【执行Python代码】 # 批量下载 results batch_download_images( yd_var[image_urls], yd_var[save_dir] ) yd_var[download_results] results 【输出结果】 成功{成功数量}张 失败{失败数量}张图片下载进阶defdownload_images_advanced(urls,save_dir,refererNone,min_size1024): 高级图片下载 min_size: 最小文件大小字节过滤占位图 results[]fori,urlinenumerate(urls,1):try:headers{User-Agent:Mozilla/5.0...}ifreferer:headers[Referer]referer# 防盗链responserequests.get(url,headersheaders,timeout15,streamTrue)ifresponse.status_code!200:continue# 检查Content-Typecontent_typeresponse.headers.get(Content-Type,)ifimagenotincontent_type:continue# 下载到临时文件extget_extension_from_url(url)filenamefimg_{i:04d}{ext}filepathos.path.join(save_dir,filename)withopen(filepath,wb)asf:forchunkinresponse.iter_content(8192):f.write(chunk)# 检查文件大小file_sizeos.path.getsize(filepath)iffile_sizemin_size:os.remove(filepath)# 太小可能是占位图results.append({url:url,status:文件太小已删除})continueresults.append({url:url,filename:filename,size:file_size,status:成功})exceptExceptionase:results.append({url:url,status:str(e)})returnresults图片去重defdeduplicate_images(image_dir):按文件MD5去重importhashlib files[fforfinos.listdir(image_dir)iff.endswith((.jpg,.png,.gif,.webp))]md5_map{}duplicates[]forfilenameinfiles:filepathos.path.join(image_dir,filename)withopen(filepath,rb)asf:file_md5hashlib.md5(f.read()).hexdigest()iffile_md5inmd5_map:duplicates.append(filepath)os.remove(filepath)# 删除重复文件print(f删除重复:{filename}(与{md5_map[file_md5]}相同))else:md5_map[file_md5]filenameprint(f去重完成共{len(files)}张删除{len(duplicates)}张重复剩余{len(md5_map)}张)returnlen(md5_map)有什么坑TEMU店群矩阵自动化运营核价报活动坑1图片防盗链# 问题直接请求图片URL返回403# 原因服务器检查Referer头# 解决设置Referer为来源页面headers{User-Agent:Mozilla/5.0...,Referer:https://example.com/# 设置来源页面}responserequests.get(image_url,headersheaders)坑2懒加载图片src是占位图# 问题img的src是loading.gif真实图片在data-src里# 但有些网站用更复杂的懒加载# 解决1优先取data-srcsrcimg.get(data-src)orimg.get(data-original)orimg.get(data-lazy)orimg.get(src)# 解决2在影刀中先滚动触发加载# 【执行JavaScript代码】# window.scrollTo(0, document.body.scrollHeight);# 【等待】2秒# 然后再提取# 解决3用Intersection Observer的网站# 需要逐个滚动到图片位置触发加载js_scroll_to_img var imgs document.querySelectorAll(img[data-src]); imgs.forEach(function(img) { img.src img.dataset.src; // 直接替换src触发加载 }); 坑3图片URL带token过期# 问题图片URL包含临时token几分钟后过期# 如https://cdn.example.com/img.jpg?tokenabc123expire1234567890# 解决提取URL后立即下载不要存起来等后面下forurlinimage_urls:# 立即下载responserequests.get(url,timeout10)# 不要先存URL列表循环到一半token就过期了坑4WebP格式图片打不开# 问题下载的.webp图片在某些软件里打不开# 解决1下载后转换为jpgfromPILimportImagedefconvert_webp_to_jpg(filepath):WebP转JPGimgImage.open(filepath)ifimg.modein(RGBA,P):imgimg.convert(RGB)jpg_pathfilepath.rsplit(.,1)[0].jpgimg.save(jpg_path,JPEG,quality95)os.remove(filepath)# 删除原webpreturnjpg_path# 解决2在影刀中用Pillow批量转换forfinos.listdir(save_dir):iff.endswith(.webp):convert_webp_to_jpg(os.path.join(save_dir,f))坑5下载到错误内容HTML而非图片# 问题URL返回的是HTML错误页面而不是图片# 下载的图片打开后是乱码# 解决检查Content-Type和文件头defis_valid_image(filepath):检查文件是否是有效图片# 检查文件头withopen(filepath,rb)asf:headerf.read(10)# JPEG: FF D8# PNG: 89 50 4E 47# GIF: 47 49 46# WebP: 52 49 46 46ifheader[:2]b\xff\xd8:returnTrue# JPEGifheader[:4]b\x89PNG:returnTrue# PNGifheader[:3]bGIF:returnTrue# GIFifheader[:4]bRIFF:returnTrue# WebPreturnFalse# 下载后验证ifnotis_valid_image(filepath):os.remove(filepath)print(f无效图片已删除:{filename})
郑州网站建设
网页设计
企业官网