[Python] requests + lxml爬取网页图片

[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中的值,这样图片就能正常查看了。至于怎么实现懒加载,各位可以开动脑经自己想想,在这就不具体实现了。


四、有待优化

  1. 这里只爬取了第一页的内容,可以外层再套个循环,爬取所有分页的图片。
  2. 图片使用简单的索引命名,可以对标题进行一些字符串处理,作为图片的名称。
  3. 其它优化…

五、总结

笔者在写这个爬虫前还是个python小白(当然写完也还是),在阅读了多篇相关的博客后,才学会了上述的爬虫方法,期间也踩过一些坑,尝试了多种解决办法,最终才成功将图片下载下来。


  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Java的世界里,HttpClient 是一个功能强大的Http请求库,然而接口非常复杂,设计上遵从正交性,简单的请求也需要比较多的代码,更不要说隐藏在各种细节里面的高级用法了。Requests,  是一个模仿python requests 模块来设计的Http lib,拥有简单而灵活的API,在容易使用的同时,又能够满足各种高级定制的使用,可是说是当前最好用的Java Http Client Lib。 简单的请求示例:String url = ...; Response resp = Requests.get(url).text(); // post 和其他方法 resp = Requests.post(url).text(); resp = Requests.head(url).text(); //读取Http Response  int statusCode = resp.getStatusCode(); Headers headers = resp.getHeaders(); Cookies cookies = resp.getCookies(); String body = resp.getBody(); //response 返回其他类型 resp = Requests.get(url).text("UTF-8"); // get response as bytes Response resp1 = Requests.get(url).bytes(); // save response as file  Response resp2 = Requests.get(url).file("/path/to/save/file"); // url 参数: Map map = new HashMap(); map.put("k1", "v1"); map.put("k2", "v2"); Response resp = Requests.get(url).param("key1", "value1").params(map)         //.params(new Parameter(...), new Parameter(...))         .text(); // 请求头 Response resp = Requests.get(url).header("key1", "value1").headers(map)         //.headers(new Header(...), new Header(...))         .text(); // 添加Cookie: Map cookies = new HashMap(); Response resp = Requests.get(url).cookie("key1", "value1").cookies(map)         //.cookies(new Cookie(...), new Cookie(...))         .text(); //  设置 userAgent Response resp = Requests.get(url).userAgent(userAgent).text(); // 增加请求数据(post, put, patch方法) // send form-encoded data. x-www-form-urlencoded header will be send automatically Response resp = Requests.post(url).data(map).text(); // send string data String str = ...; resp = Requests.post(url).data(str, "UTF-8").text(); // send from inputStream InputStream in = ... resp = Requests.post(url).data(in).text(); // multipart 请求, 用于文件上传: Response resp = Requests.post(url).data(map).multiPart("ufile", "/path/to/file")         .multiPart(..., ...).text();请求设置://禁止自动重定向

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值