第五章 Electron|Node 使用cheerio 爬虫

news2025/1/11 8:50:51

一、cheerio是什么可以做什么 👇 👇 👇

Cheerio是一个快速、灵活且精益的jQuery核心实现,用于在Node.js环境中解析HTML文档。它可以帮助您在服务器端轻松地从HTML文档中提取数据,比如从网页中提取文章标题、内容、图片等信息。

二、为什么选择cheerio 👇 👇 👇

使用Cheerio的好处是它非常轻量级,因此可以很快地加载和解析HTML文档。此外,Cheerio的API与jQuery非常相似,因此如果您熟悉jQuery,那么学习和使用Cheerio也会非常容易。

三、安装依赖 👇 👇 👇

yarn add cheerio

我安装的版本

四、爬虫的资源以及资源分析 👇 👇 👇

这里以电脑壁纸 高清电脑壁纸大全 高清手机壁纸 彼岸桌面壁纸为例。本文只为学习,请不要对网站进行恶意攻击。

打开网站以后分析页面,页面结构我们只需要三个部分。一是分类,而是图片显示区域以及分页。

1、获取分类 👇 👇 👇

打开浏览器控制台

使用cheerio对应的代码如下,这里面的话有个核心的就是中文乱码的处理啊。

getPageInfo() {
    // {responseType: 'arraybuffer', responseEncoding: 'utf-8'} 这里是配置返回结果中文乱码的解决方案
    axios.get(this.source, {responseType: 'arraybuffer', responseEncoding: 'utf-8'}).then((res: any) => {
        // 中文乱码的解决方案
        let utf8decoder = new TextDecoder("GBK")
        const $: any = cheerio.load(utf8decoder.decode(res.data))
        // 分类
        const classify = $('.menu .cate')[0]['children']
        if (classify?.length) {
            const data = classify.filter((item: Element) => item.tagName === 'a')
            this.classifyList = data.map((item: Element) => {
                return !item.attributes[0].value.includes('http') && {
                    name: (item.children[0] as unknown as Text).data,
                    path: item.attributes[0].value
                }
            })
        }
    })
},

2、获取资源 👇 👇 👇

具体实现的代码如下。分页的逻辑也是一样的。自行分析,分页的获取代码也写在了一起。

getClassifyInfo(item: ClassifyType) {
    this.currentClassify = item
    this.currentIndex = 1
    this.currentResult = []
    axios.get(`${this.source}${item.path}`, {responseType: 'arraybuffer', responseEncoding: 'utf-8'}).then((res: any) => {
        // 中文乱码的解决方案
        let utf8decoder = new TextDecoder("GBK")
        const $: any = cheerio.load(utf8decoder.decode(res.data))
        this.splicing($)
    })
},
splicing($: any) {
    // 获取页面上的图片
    const list = $('#main .list ul li img')
    for (let i = 0; i < list.length; i++) {
        if ((list[i] as Element).attributes[0] && (list[i] as Element).attributes[1]) {
            this.currentResult.push({
                name: (list[i] as Element).attributes[1].name,
                path: (list[i] as Element).attributes[0].value
            })
        }
    }
    // 获取分页
    const page = $('#main .page').children()
    if (page[page.length - 1]) {
        let val: Text = page[page.length - 2].children[0]
        this.pageTotal = (val.data as any) - 0 || 0
    }
},

我使用的是pinia状态管理器,整个爬虫的代码如下:

完整代码

import { defineStore } from 'pinia';
import axios from "axios";
// @ts-ignore
const cheerio = require('cheerio')

export interface ClassifyType {
    name: string
    path: string
}

/**
 * @Description: 壁纸
 * @CreationDate 2023-05-31 17:04:13
 */
interface WallpaperModule {
    source: string // 源
    classifyList: ClassifyType[] // 分类
    currentClassify?: ClassifyType // 当前分类
    pageTotal: number // 总页数
    currentIndex: number // 当前分页
    currentResult: ClassifyType[] // 当前搜索出来的结果
}

/**
 * @Description: 壁纸爬取
 * @Author: Etc.End(710962805@qq.com)
 * @Copyright: TigerSong
 * @CreationDate 2023-05-31 17:01:36
 */
export const wallpaperModule = defineStore({
    id: 'wallpaper',
    state(): WallpaperModule {
        return {
            source: 'http://www.netbian.com',
            classifyList: [],
            pageTotal:0,
            currentIndex: 1,
            currentResult: []
        }
    },
    actions: {
        getPageInfo() {
            // {responseType: 'arraybuffer', responseEncoding: 'utf-8'} 这里是配置返回结果中文乱码的解决方案
            axios.get(this.source, {responseType: 'arraybuffer', responseEncoding: 'utf-8'}).then((res: any) => {
                // 中文乱码的解决方案
                let utf8decoder = new TextDecoder("GBK")
                const $: any = cheerio.load(utf8decoder.decode(res.data))
                // 分类
                const classify = $('.menu .cate')[0]['children']
                if (classify?.length) {
                    const data = classify.filter((item: Element) => item.tagName === 'a')
                    this.classifyList = data.map((item: Element) => {
                        return !item.attributes[0].value.includes('http') && {
                            name: (item.children[0] as unknown as Text).data,
                            path: item.attributes[0].value
                        }
                    })
                }
            })
        },
        getClassifyInfo(item: ClassifyType) {
            this.currentClassify = item
            this.currentIndex = 1
            this.currentResult = []
            axios.get(`${this.source}${item.path}`, {responseType: 'arraybuffer', responseEncoding: 'utf-8'}).then((res: any) => {
                // 中文乱码的解决方案
                let utf8decoder = new TextDecoder("GBK")
                const $: any = cheerio.load(utf8decoder.decode(res.data))
                this.splicing($)
            })
        },
        splicing($: any) {
            // 获取页面上的图片
            const list = $('#main .list ul li img')
            for (let i = 0; i < list.length; i++) {
                if ((list[i] as Element).attributes[0] && (list[i] as Element).attributes[1]) {
                    this.currentResult.push({
                        name: (list[i] as Element).attributes[1].name,
                        path: (list[i] as Element).attributes[0].value
                    })
                }
            }
            // 获取分页
            const page = $('#main .page').children()
            if (page[page.length - 1]) {
                let val: Text = page[page.length - 2].children[0]
                this.pageTotal = (val.data as any) - 0 || 0
            }
        },
        next(type: string) {
            if (this.currentClassify) {
                this.currentResult = []
                this.currentIndex = type === 'left' ? this.currentIndex - 1 : this.currentIndex + 1
                axios.get(`${this.source}${this.currentClassify.path}index_${this.currentIndex}.htm`, {responseType: 'arraybuffer', responseEncoding: 'utf-8'}).then((res: any) => {
                    // 中文乱码的解决方案
                    let utf8decoder = new TextDecoder("GBK")
                    const $: any = cheerio.load(utf8decoder.decode(res.data))
                    this.splicing($)
                })
            }
        }
    },
    getters: {},
});

五、编写渲染页面 👇 👇 👇

这里的话有个小问题,就是直接访问我们爬取的图片会返回401,只需要再index.html里面头部加入一个配置

<meta name="referrer" content="no-referrer" />
<template>
    <div>
        <div class="wallpaper-classify">
            <template v-for="(item, index) in classifyList">
                <div class="wallpaper-classify-item" v-if="item.name" :key="index" @click="getClassifyInfo(item)">{{item.name}}</div>
            </template>
        </div>
        <div style="display: flex;flex-direction: row;flex-wrap: wrap;justify-content: center;align-items: center;">
            <template v-for="(item, index) in currentResult">
                <el-image :preview-src-list="[item.path]" style="width: 300px;height: 169px;margin: 0 26px 20px 0;" :src="item.path" :alt="item.name"></el-image>
            </template>
        </div>
        <div v-if="pageTotal > 0" style="display: flex;justify-content: center;align-items: center;">
            <div style="margin-left: 20px;">当前在第 <span style="color: #009169">{{currentIndex}}</span> 页</div>
            <el-button size="small" style="margin-left: 20px;" v-if="currentIndex > 1" @click="goPage('left')">
                <template #icon>
                    <i-noto-backhand-index-pointing-left/>
                </template>
                上一页
            </el-button>
            <el-button size="small" style="margin-left: 20px;" v-if="currentIndex < pageTotal" @click="goPage('right')">
                <template #icon>
                    <i-noto-backhand-index-pointing-right/>
                </template>
                下一页
            </el-button>
            <div style="margin-left: 20px;">共 <span style="color: #009169">{{pageTotal}}</span> 页</div>
        </div>
    </div>
</template>

<script lang="ts">
import {defineComponent, onMounted, reactive} from "vue";
import appStore from "@/pinia";
import {storeToRefs} from "pinia";
import {ClassifyType} from "@/pinia/modules/wallpaper.modules.ts";

export default defineComponent({
    setup() {

        const { classifyList, currentResult, pageTotal, currentIndex } = storeToRefs(appStore.wallpaperModule)

        const getClassifyInfo = (item: ClassifyType) => {
            appStore.wallpaperModule.getClassifyInfo(item)
        }

        const goPage = (type: string) => {
            appStore.wallpaperModule.next(type)
        }

        onMounted(() => {
            appStore.wallpaperModule.getPageInfo()
        })

        return {
            classifyList,
            getClassifyInfo,
            currentResult,
            pageTotal,
            currentIndex,
            goPage,
        }
    }
})
</script>

<style scoped lang="scss">
    .wallpaper-classify {
        display: flex;
        padding: 20px 10px;
        justify-content: center;
        align-items: center;
    }
    .wallpaper-classify-item {
        cursor: pointer;
        & + & {
            margin-left: 12px;
        }
        &:hover {
            color: #03a9a9;
            border-bottom: 1px solid #03a9a9;
        }
    }
</style>

到这这一步就完成所有的代码了。你还可以接着扩展,比如下载图片等等

我是Etc.End。如果文章对你有所帮助,能否帮我点个免费的赞和收藏😍。

 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/602303.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JVM】.class文件如何在JVM中运行的?

一、先认识JVM的组成 java虚拟机整体包括&#xff1a;类加载系统、运行时数据区、执行引擎、垃圾回收器。 &#xff08;1&#xff09;方法区&#xff1a;线程共享&#xff0c;存储Class信息、常量、静态变量等等&#xff1b; jdk1.6~1.7时称为永久代&#xff0c;存储常量、Cla…

js常见面试题整理

1&#xff1a;JavaScript 有哪些数据类型 答&#xff1a; JavaScript 的数据类型分为原始类型和对象类型。 原始类型有 7 种&#xff0c;分别是&#xff1a; BooleanNumberBigIntStringNullUndefinedSymbol 对象类型&#xff08;也称引用类型&#xff09;是一个泛称&#x…

vue3 中使用indexDb

1.indexDb.js const indexDB window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB; class IndexDBCache {// 构造函数constructor() {this._db null; //数据库this._transaction null; //事务this._request null;this._dbName "loginInfoDb"; …

API ‘variantOutput.getPackageLibrary()‘已过时的解决方法

一个发布到maven central的android库项目&#xff0c;为了方便管理&#xff0c;在build.gradle文件中加入了打包处理的一段脚本&#xff1a; //生成aarlibraryVariants.all { variant ->def name "library-${versionMajor}.${versionMinor}.${versionPatch}.aar"…

VUE 3.0 + NGINX + Hls.js + OBS -- 直播推拉流、流视频播放

&#x1f6f4;&#x1f6f4;前言&#xff1a; 该 Demo 基于 OBS推流 Nginx Vue 3.0 Nplayer.js hls.js &#xff0c;目的只是实现流媒体播放&#xff0c;以及简易推拉流直播。 文章目录 前端组件 NPlayer.js安装 nplayer.js 流视频播放页面元素初始化播放器清晰度控件样式…

D*算法详解 (D星算法 / Dynamic A*算法/ Dstar算法)(死循环解决)

所需先验知识&#xff08;没有也无大碍&#xff0c;只是了解的话会对D*的理解有帮助&#xff09;&#xff1a;A*算法/ Dijkstra算法 何为D*算法 Dijkstra算法是无启发的寻找图中两节点的最短连接路径的算法&#xff0c;A*算法则是在Dijkstra算法的基础上加入了启发函数h(x)&am…

js正则中的match()

在前端开发中&#xff0c;正则表达式是一大利器。所以我们这次就来讨论下match()方法。 match本身是JavaScript语言中字符串对象的一个方法&#xff0c;该方法的签名是 match([string] | [RegExp]) 它的参数既可以是一个字符串&#xff0c;也可以是一个正则表达式。该方法绝…

windows 达梦数据库服务连接时提示:登录服务器失败,错误号6001,错误消息:网络通信异常 之数据库服务不存在的处理方式

在windows客户端上连接部署在windows操作系统上的达梦数据库&#xff0c; 使用DM管理工具连接数据库 正确输入用户名与密码之后点击确定按钮之后出现&#xff1a; 登录服务器失败&#xff0c;错误号6001&#xff0c;错误消息&#xff1a;网络通信异常 现象 如下图所示&#…

银行从业资格证 个人理财 各种年金计算公式总结

变量说明&#xff1a; C C C &#xff1a;每期投入的现金流 r r r&#xff1a;利率&#xff08;收益率/贴现率&#xff09; n n n &#xff1a;计息期数&#xff1b; F V FV FV&#xff1a;终值 P V PV PV&#xff1a;现值 推导计算过程用到等比数列求和公式 S n a 1 ∗ 1 −…

【算法训练(day7)】区间和并,离散化数组模板

目录 一.区间和并 二 .离散化数组 一.区间和并 问题&#xff1a;给定 n个区间 [li,ri]&#xff0c;要求合并所有有交集的区间。注意如果在端点处相交&#xff0c;也算有交集。输出合并完成后的区间个数。例如&#xff1a;[1,3][1,3] 和 [2,6][2,6] 可以合并为一个区间 [1,6][1…

htmlCSS-----CSS介绍与样式书写

目录 前言&#xff1a; 1. CSS是什么 2. CSS书写样式 (1)行内样式 (2)内部样式 3.外部样式 4.三者之间的比较 前言&#xff1a; 前面我们学习了HTML的相关标签和框架写法&#xff0c;那我们在了解这些标签用法了之后就要学会怎么去通过相关方法来使得界面美化处理&#xf…

06 Redis分布式锁

常见面试问题 Redis除了拿来做缓存&#xff0c;你还见过基于Redis的什么用法&#xff1f;Redis 做分布式锁的时候有需要注意的问题&#xff1f;如果是 Redis 是单点部署的&#xff0c;会带来什么问题&#xff1f;那你准备怎么解决单点问题呢&#xff1f;集群模式下&#xff0c…

LeetCode刷题集(七)(2315.统计星号)

&#x1f626;学习目标&#xff1a;拿下LeetCode2315.统计星号题目 &#x1f624; 学完本章节知识即可掌握本题&#xff01; 学习内容&#xff1a;LeetCode2315.统计星号 &#x1f624;题目&#xff1a;给你一个字符串 s &#xff0c;每 两个 连续竖线 ‘|’ 为 一对 。换言之&…

知识图谱涉及技术点分析

文章目录 数据从哪里来为什么通常将知识图谱划分到NLP领域&#xff1f;常用NLP技术点分析只是NLP任务吗&#xff1f;graph embedding知识融合业务还是算法&#xff1f;知识图谱组成 数据从哪里来 是手动提取关系吗&#xff1f;数据很多&#xff0c;关系确难涉及大量NLP技术关系…

Ansible基础五——条件语句、循环语句、handlers、任务失败处理

文章目录 一、 循环语句1.1 单量循环1.2 多量循环1.3 老版本用法1.4 loopregister 二、条件判断2.1 根据变量状态判断2.2 根据变量是否存在判断2.3 根据事实判断2.4 多条件判断2.4.1 and用法2.4.2 or用法 2.5 循环判断2.6 根据上个任务结果判断 三、handlers处理程序四、任务失…

5月《中国数据库行业分析报告》正式发布,首发时序、实时数据库两大【全球产业图谱】

为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况&#xff0c;从2022年4月起&#xff0c;墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》&#xff0c;持续传播数据技术知识、努力促进技术创新与行业生…

ubuntu20安装xrdp以及解决黑屏问题

1、安装xrdp sudo apt-get install xrdp 2、将xrdp用户加入到如下用户组 sudo adduser xrdp ssl-cert 3、重启xrdp sudo service xrdp restart 4、打开windows远程面&#xff0c;连接&#xff0c;如果出现黑屏 sudo -s sudo vim /etc/xrdp/startwm.sh 加入如下内容&#xff…

攻防世界-web-Web_php_unserialize

1. 题目描述&#xff1a;查看以下代码&#xff0c;获取flag 2. 思路分析 从代码中不难看出&#xff0c;这里共有三个地方需要绕过 2.1 __wakeup函数&#xff1a;若在对象的魔法函数中存在的__wakeup方法&#xff0c;那么之后再调用 unserilize() 方法进行反序列化之前则会先…

数据分析概述

数据分析概述 数据的性质数据的概念数据与信息的区别和联系 数据的类型按照度量尺度分按时间状况分 什么是数据分析数据分析的重要性数据分析的内容数据分析作用 数据分析的基本流程典型的数据分析的流程 数据分析方法对比分析法分组分析法定量数据分布分析——具体事例 结构分…

上海亚商投顾:沪指高开高走 地产股迎来久违反弹

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 三大指数今日高开高走&#xff0c;沪指午后涨近1%&#xff0c;深成指、创业板指涨超1.2%&#xff0c;上证50盘中大…