[Python] requests + lxml爬取图片
使用python中的requests库和lxml库爬取特定网站上的图片。
一、模块介绍
1. requests模块
requests库是一个python第三方库,基于urllib编写,用于发送网络请求,访问网络资源。
常用方法
# 使用前导入模块
import requests
url = 'http://www.baidu.com'
param = {'key': 'value'}
header = {'User-Agent': 'Mozilla/5.0 ......'}
# 发送get请求
response = requests.get(url)
response = requests.get(url, param=param, header=header)
# 发送post请求
response = requests.post(url, data=param)
print(response.content)
2. lxml模块
lxml是一个HTML/XML解析库,用于解析和提取HTML/XML数据。
lxml解析时使用xpath定位特定元素以及节点信息。
# 使用前导入模块
from lxml import etree
content = """
# 一段网页代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>我是标题</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>
<p>我的第二个段落。</p>
</body>
</html>
"""
html = etree.HTML(content)
pp = html.xpath('/html/body/p/text()')
for p in pp:
print(p)
结果
二、爬取过程
1. 分析网页图片元素
f12检查网页元素
2. 编写xpath定位图片的链接属性
在该网页中图片元素都是在div下的article标签里的a标签下,而图片的链接则是在各个img标签的属性(src和data-src)中,更据这个规律可以写出图片链接的 xpath
xpath = '//article/div/a/img/@data-src'
这里为什么选择data-src属性而不是src属性呢,文章末尾会做解释。
3. 编写脚本爬取图片
这里直接贴全部代码,代码量很少,直接看注释即可。
import requests
from lxml import etree
# 网页路径
url = 'https://xxx.xxx.com/category/nsgames?tag=only_on_consoles'
# 请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
'Referer': 'https://xxx.xxx.com/category/nsgames?tag=only_on_consoles'
}
# 图片保存路径
savePath = 'D:\\OneDrive\\桌面\\images\\'
# 设置请求头 发送请求 (不设置Referer图片会下载失败)
response = requests.get(url, headers=headers)
content = response.content.decode('utf-8')
print(content)
# 解析返回的网页内容
html = etree.HTML(content)
# 先获取父级article节点
articles = html.xpath('//article[contains(@class,"type-post")]')
print(articles)
idx = 0
for article in articles:
# 再获取每个article中的图片元素和标题元素
imageUrl = article.xpath('.//a/img/@data-src')[0]
print(imageUrl)
title = article.xpath('.//header/h2/a/text()')[0]
print(title)
path = savePath + str(idx) + '.jpg'
idx += 1
print(path)
# 保存图片到本地
image = requests.get(imageUrl, headers=headers)
with open(path, 'wb') as f:
f.write(image.content)
4. 爬取结果
运行结果
保存的图片
三、注意事项
1. 请求头需要设置Referer
referer的作用是告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理,比如防止外链访问。
在这里也是这个道理,如果没有加上referer,服务器会判断请求为外链而不响应正确的资源,下载的图片会变成这样
可以看到图片提示“网站图片不支持外链请见谅”
有趣的是,Referer的正确英语拼法是referrer。由于早期HTTP规范的拼写错误,为了保持向后兼容就将错就错了。
2. 图片的属性选择data-src而不是src
当我们f12查看网页元素时,发现src属性值和data-src属性值是一样的,都是图片路径。但是如果我们爬取的时候xpath定位的是src属性,则会获取不到图片的路径导致下载失败。为什么会这样呢,这涉及到图片的懒加载机制。
图片懒加载机制:页面加载时,不一次性把所有图片都加载完,而是优先加载可视区域的内容,其他部分等进入了可视区域再加载,从而提高性能。
这里的data-src就是用来实现懒加载的,原理是这样的,服务器返回的每个img元素的data-src都存放着图片的路径,但是src属性值却设置成一张较小图片的路径或者直接设置为空。当滚动条滚动,图片进入可视区域时,再将src属性值设置为data-src中的值,这样图片就能正常查看了。至于怎么实现懒加载,各位可以开动脑经自己想想,在这就不具体实现了。
四、有待优化
- 这里只爬取了第一页的内容,可以外层再套个循环,爬取所有分页的图片。
- 图片使用简单的索引命名,可以对标题进行一些字符串处理,作为图片的名称。
- 其它优化…
五、总结
笔者在写这个爬虫前还是个python小白(当然写完也还是),在阅读了多篇相关的博客后,才学会了上述的爬虫方法,期间也踩过一些坑,尝试了多种解决办法,最终才成功将图片下载下来。