Python爬虫 爬取懒加载页面(以站长素材为例)

一.什么是懒加载

我就简单的说一下。当你去访问一个页面的时候,这个页面可能会有很多的信息,比如淘宝,京东之类的。如果你一次性完整的加载出这个页面。显然耗时长一点,并且对于用户和服务器都是不友好的。懒加载就是当 某个图片的位置在你的屏幕范围之内,它才会加载出来。这个是比较好理解的。

(这个懒加载对用户和服务器都是比较友好的,但是对于我们爬虫来说就比较蛮烦了。往往用xpath或者bs4取解析数据的时候,就不准确。)

我们看看下面这张图片有个src2属性,我们知道img标签没有这个属性,只有src属性。所以这个是伪属性它可以是src2也可以是abc之类的,所以浏览器不会去加载。在小众范围的网站中,这种懒加载是常用的方法。
在这里插入图片描述
注意到这个src2之后,我洋洋得意。但是在我爬取的过程中,却没有返回到任何的数据。这就很奇怪,于是我打印xpath返回的列表对象长度。(下面展示我省略一部分代码完整代码在文章末尾)

response = requests.get(url=url, headers=headers)
response.encoding = 'utf-8'
page_text = response.text
tree = etree.HTML(page_text)
a_list = tree.xpath('//div[@class="box picblock col3 masonry-brick"]/div/a/img') 
print(len(a_list))

一页有40张图片,照理说打印出40才对,我之前在网页上试了一下xpath路径如下。40个一点没错
在这里插入图片描述
但是事与愿违打印出来的是0在这里插入图片描述
这就让我捉摸不透了,不知道是哪出了问题。我就怀疑可能xpath部分出了问题,那我就先定位到包裹着每个图片的div所以我更改了xpath
前:’//div[@class=“box picblock col3 masonry-brick”]/div/a/@href’
后:’//div[@class=“box picblock col3 masonry-brick”]'
但是打印出来的仍然是0。这就很奇怪。

我怀疑八成这个class也被伪装了,伪装的不是属性,而是属性里面的内容。但是就懒加载来说,不应该class出问题。因为在这之前我看了一些还没加载的图片,这些图片的class名都是 box picblock col3 masonry-brick 。那就是返回的数据可能有问题,于是我就把page_text打印出来,想看看我获取到底是什么数据。然后查看了我获取的class

print(page_text)

在这里插入图片描述
结果这里获取的class也是个伪元素。属性值被伪装了。

但是这我有个疑问既然是懒加载,那么我没加载出来的那些图片的class为什么没有伪装。
仔细思考一下,用requests请求是没有浏览窗口大小这个概念的。所以页面的所有能被伪装的标签元素都是以伪元素的形式存在的。
当人去浏览的时候,只看见了部分的class属性值。这个class名就当是一个集体吧,要加载就全部加载出来了,而对于src属性是针对单个图片的,服务器加载可能有些吃力(我是这样理解的)所以只有浏览到的时候才会加载出来。requests没有窗口的概念,所以当请求时这个class一直是伪装的状态。我们只能用伪装的属性去请求

a_list = tree.xpath('//div[@class="box picblock col3"]/div/a/@href') 
print(len(a_list))

唉!一番尝试以后更换了class名以后,打印出来终于是40了
在这里插入图片描述
好了,现在我们知道了伪class名和伪src那么我就能爬取图片了。接下来的过程就很简单了。和普通网上爬取图片是一样的。

我们理一下思路:

  • 首先我们请求页面就是代码的1-13行,这比较好懂
  • 然后用utf-8译码,否则会出现乱码,获取文本内容加载到对象tree里面
  • 然后循环遍历返回的列表数据,利用xpath解析数据,只要注意好这里的属性src2即可
  • 保存数据到本地
    具体请看下面的完整代码我也做了注释
import requests
from lxml import etree
import os
#我们创建一个站长素材文件夹
if not os.path.exists('素材'):
    os.mkdir('素材')

headers = {
    'User-Agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
}
url = 'http://sc.chinaz.com/tupian/fengjingtupian.html'
response = requests.get(url=url, headers=headers)
#对返回的数据进行译码,否则会乱码
response.encoding = 'utf-8'
#得到page_text
page_text = response.text
tree = etree.HTML(page_text)
#利用xpath定位到img标签,注意这里的class名,别被迷惑了
img_list= tree.xpath('//div[@class="box picblock col3"]/div/a/img') 
#循环遍历返回的列表
for img in img_list:
#列表中的img也是tree类型的,所以我们可以再具体的定位到属性
    title=img.xpath('./@alt')[0]
    img_url=img.xpath('./@src2')[0]
    #图片是byte类型,用content属性写入到文件里面
    img_data=requests.get(img_url,headers=headers).content
    with open('站长素材/'+title+'.jpg','wb')as fp:
        fp.write(img_data)
    print(title+'打印成功')

这就是突破懒加载,爬取图片的过程。当然这个爬取的只是页面中的小图,如果你想爬取大图也行,那我们就不用定位到img了,我们定位到a标签,然后获取其href属性,然后利用requests请求,再到详情页去定位到真正的原图。这个我也写好了你可以参考一下:

import requests
from lxml import etree
import os

if not os.path.exists('站长素材'):
    os.mkdir('站长素材')

headers = {
    'User-Agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
}
url = 'http://sc.chinaz.com/tupian/fengjingtupian.html'
response = requests.get(url=url, headers=headers)
response.encoding = 'utf-8'
page_text = response.text
tree = etree.HTML(page_text)
a_list = tree.xpath('//div[@class="box picblock col3"]/div/a/@href')
for a in a_list:
    child_response = requests.get(a, headers=headers)
    child_response.encoding = 'utf-8'
    child_page = child_response.text
    child_node = etree.HTML(child_page)
    try:
        img_src = child_node.xpath('//div[@class="imga"]//a/@href')[0]
        img_title = child_node.xpath('//div[@class="imga"]//a/@title')[0]
        img_data = requests.get(url=img_src, headers=headers).content
        with open('站长素材/' + img_title + '.jpg', 'wb') as fp:
            fp.write(img_data)
        print(img_title + '.jpg打印成功')
    except Exception as e:
        print(e)

和之前的很像对不对,这里我加了一个try,因为有些图片是无效的,所以会报错,程序停止运行。
了解了懒加载,就又掌握了一门反反爬技术。

  • 14
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
回答: 要实现Python爬虫爬取多个页面,可以采用增量爬虫的方式。增量爬虫是通过监测网站更新的情况,只抓取最新数据的一种方式,可以大大降低资源的消耗。当第一次运行爬虫程序时,爬虫会将所有的url抓取下来,并将这些url放入数据库中,并为每一个url生成专属的“指纹”。当网站更新后,第二次运行爬虫程序时,程序只会对数据库中不存在的指纹进行抓取,从而获取新数据的信息。这样可以避免重复抓取已经抓取过的数据,提高爬取效率。\[1\]\[3\]另外,如果要爬取动态加载的数据,可以通过查看页面源代码,找到数据加载的JS函数,并模拟执行该函数来获取数据。\[2\] #### 引用[.reference_title] - *1* *3* [Python爬虫:抓取多级页面数据](https://blog.csdn.net/pythonhy/article/details/128784799)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Python 爬虫爬取多页数据](https://blog.csdn.net/weixin_39583222/article/details/109936174)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值