参考‘逆風的薔薇’的教程,《Python3爬虫》-爬取豆瓣首页图片
代码
采用伪装浏览器形式,增加图像处理和存储模块。
'''
re模块提供对正则表达式的支持
os模块提供对系统接口层面的支持
'''
import urllib.request, re, os
targetPath = r'E:\Python\VSCode_Python\CSDN\project\03_dbImages'
def saveFile(path):
# 路径有效性检测
if not os.path.isdir(targetPath):
os.mkdir(targetPath) # 如果没有该路径就生成该路径
# 设置图片路径
pos = path.rindex('/') # 返回/在字符串中最后出现的位置,以获取图片名称
t = os.path.join(targetPath, path[pos+1:])
return t # saveFile用于生成一个路径,配合urlretrieve使用
url = 'https://www.douban.com/'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.7 Safari/537.36'}
req = urllib.request.Request(url=url, headers=headers)
res = urllib.request.urlopen(req)
data = res.read()
# re.findall(pattern, string, flags=0) 搜索string,以列表形式返回全部能匹配的字符串
# 正则表达式,https:[^s]*?(jpg|png|gif),[^\s]表示匹配非空格,*表示匹配前面的表达式任意次,?表示非贪婪匹配,(jpg|png|gif)表示匹配jpg或png或gif
# * +等都是贪婪匹配,后面再加?则变成非贪婪匹配
# re.match,只匹配字符串的开始,如果开始不匹配则匹配失效返回None
# re.search,匹配整个字符串,直到找到一个匹配
# re.findall,遍历整个字符串
for link, t in re.findall(r'(https:[^\s]*?(jpg|png|gif))', str(data)):
print(link)
try:
urllib.request.urlretrieve(link, saveFile(link))
# urlretrieve(url, filename=None, reporthook=None, data=None) 将link链接上的这张图片拷贝至本地filename路径
print('保存成功')
except:
print('保存失败')
print('Done!')
运行结果
控制台输入如下:
抓取的图片如下:
笔记
- os模块,提供系统接口层面的支持,掌握isdir、mkdir、path.rindex和join等的使用,相关说明OS模块
- re模块,提供对于正则表达式的支持,掌握match、search、findall等的使用以及基本的正则表达式规则,相关说明re模块
- urlretrieve的使用
- 原教程中正则表达式为
https:[^s]*?(jpg|png|gif)
抓取的图片要少一些,而更正为
https:[^\s]*?(jpg|png|gif)
抓取的图片更为全面。[^\s]表示匹配非空格字符,而如果说[^s]表示匹配非s又说不通,因为根据原表达式没有s但是有空格的也没有匹配成功,这里暂时不太明白。
- 有朋友对循环的表示有疑问,为什么要用link,t两个变量,一个不可以吗?
for link, t in re.findall(r'(https:[^\s]*?(jpg|png|gif))', str(data)):
可以看一下经过re.findall处理之后的结果,是一组列表,列表中每个元素包含两个字符串,图片的网址以及图片的格式,而我们在进行urlretrieve处理时只需要图片的网址,因此用了link和t两个变量,如果只用link,只需将后面的link改为link[0]也没有问题。