安装需求
-
Python 环境
-
爬虫相关Python 第三方库
第三方库安装
-
requests
pip install requests
-
该模块用于请求网页,是爬虫必备模块
爬取目标分析
-
浏览网页源码,分析网页结构
-
可以看出在https://burst.shopify.com/photos
https://burst.shopify.com/photos页面下列出了所有图片,并且有通过分页排列,分页规律是https://burst.shopify.com/photos?page= (页数)
-
具体到每张图片元素的url,都嵌在<div class="grid ">标签下
-
而在图片的详情页中我们还可以发现这个网站本身就提供了下载链接,就是在这个详情页的url后面加上/download,但是爬虫不是靠这个运行的,我们接下来找到的是这里
-
这一段里.jpg就十分明显,但是后面还有一段限制长宽像素的我们在爬取的时候应该删去,否则只会爬到一些缩略图,而不是原图
结构构造
import requests # 抓取函数 def main(): pass # 解析函数 def format(): pass # 存储函数 def save_image(): pass if __name__ == '__main__': main()
抓取语句构造
def main(): url = "https://burst.shopify.com/photos" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36" } res = requests.get(url=url, headers=headers, timeout=5) print(res.text)
-
这条抓取语句抓取的是整个网页的源码,抓下来以后才可以进行下一步解析源码,取得存在图片的url
-
这里的headers配置是为了在请求网页时将爬虫的请求伪造成貌似正常的访问请求,防止图片下载失败
解析语句构造
-
通过教程我学习了直接字符串拼接配合正则表达式来获取到图片详情页地址
-
前面我们已经对访问网页上图片的逻辑进行过分析,所以第一步就是拆解字符串,取出目标数据部分,让爬虫获取各个分页中的各个图片的url
def format(text): # 处理字符串 div_html = '<div class="grid ">' page_html = '<section class="section section--tight section--padding-top-only">' start = text.find(div_html) + len(div_html) end = text.find(page_html) origin_text = text[start:end] return origin_text pass
-
在这各部分截取了从'<div class="grid ">'到'<section class="section section--tight section--padding-top-only">'的所有源码,其中很多都是对爬虫来说无用的,所以我们还要用正则表达式筛选一遍,括号的作用也是形成列表为了后续方便提取。
import re def format(text): # 处理字符串 div_html = '<div class="grid ">' page_html = '<section class="section section--tight section--padding-top-only">' start = text.find(div_html) + len(div_html) end = text.find(page_html) origin_text = text[start:end] # 正则表达式筛选 pattern = re.compile('href="(.*?)"') hrefs = pattern.findall(origin_text) return hrefs
-
使用的技术是 re 模块,
re.compile('href="(.*?)"')
-
这一段用正则表达式匹配了所有在href后面的字符串
-
和前面的抓取语句的代码相结合运行一遍看看
-
除了我们需要的'/photos/person-stands-on-rocks-poking-out-of-the-ocean-shoreline'这样的字符之外,还能看到很多不必要的字符,这里要再次进行筛选
pattern = re.compile('href="(.*?)"') hrefs = pattern.findall(origin_text) hrefs = [i for i in hrefs if i.find("photos")>0]
-
再运行试试
抓取内页数据
-
已经获取了这一页的所有图片的url,下一步就是去获取这些url里的数据了
for href in hrefs: url = f"https://burst.shopify.com{href}" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36" } res = requests.get(url=url, headers=headers, timeout=5) res.encoding = "GBK" format_detail(res.text) break # 格式化细节 def format_detail(text): # 处理字符串 div_html = '<div class="photo__download">' page_html = '<div class="photo__social-shares-container">' start = text.find(div_html) + len(div_html) end = text.find(page_html) origin_text = text[start:end] pattern = re.compile('data-modal-image-url="(.*?)"') src = pattern.findall(origin_text) src = src[0] image_src = '' for i in range(0,len(src)+1): if src[i] != "?": image_src =image_src +src[i] if src[i] == "?": break return image_src
-
这里处理字符串在没在教程里找到可借鉴的,就自己写了一段很垃圾的代码来处理图片url后面对图片像素的限制,是直接处理字符串得到结果
保存语句构造
-
保存图片部分,需要提前导入
time
模块,对图片进行重命名。
# 存储函数 def save_image(image_src): res = requests.get(url=image_src, timeout=5) content = res.content with open(f"{str(time.time())}.jpg", "wb") as f: f.write(content)
-
使用
requests.get
方法直接请求图片地址,调用响应对象的content
属性,获取二进制流,然后使用f.write
存储成图片。
第一张图测试结果
-
桌面上的图片就是爬取结果
-
看文件大小也是高清图片
代码优化
import re import time import requests # 请求函数 def request_get(url, ret_type="text", timeout=5): headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36" } res = requests.get(url=url, headers=headers, timeout=timeout) if ret_type == "text": return res.text elif ret_type == "image": return res.content # 抓取函数 def main(): urls = [f"https://burst.shopify.com/photos?page={i}" for i in range(2, 201)] url = "https://burst.shopify.com/photos" urls.insert(0, url) for url in urls: print("抓取列表页地址为:", url) text = request_get(url) format(text) # 解析函数 def format(text): # 处理字符串 origin_text = split_str(text, '<div class="grid ">', '<section class="section section--tight section--padding-top-only">') # 正则表达式筛选 pattern = re.compile('href="(.*?)"') hrefs = pattern.findall(origin_text) hrefs = [i for i in hrefs if i.find("photos")>0] for href in hrefs: url = f"https://burst.shopify.com{href}" print(f"正在下载:{url}") text = request_get(url) format_detail(text) # 格式化细节 def format_detail(text): # 处理字符串 origin_text = split_str(text, '<div class="photo__download">', '<div class="photo__social-shares-container">') pattern = re.compile('data-modal-image-url="(.*?)"') src = pattern.findall(origin_text) src = src[0] image_src = '' for i in range(0,len(src)+1): if src[i] != "?": image_src =image_src +src[i] if src[i] == "?": break save_image(image_src) #字符分割 def split_str(text, s_html, e_html): start = text.find(s_html) + len(e_html) end = text.find(e_html) origin_text = text[start:end] return origin_text # 存储函数 def save_image(image_src): content = request_get(image_src, "image") with open(f"{str(time.time())}.jpg", "wb") as f: f.write(content) print("图片保存成功") if __name__ == '__main__': main()
运行结果
-
截图的时候还在下载,下载速度慢这个问题可以做一下多线程优化