Python网络爬虫实战6—下一页,模拟用户点击,切换窗口

news2024/12/26 0:49:19

【前期提要】感兴趣的可以看看往期文章哈~
Python网络爬虫5-实战网页爬取
Python网络爬虫4-实战爬取pdf
Pyhon网络爬虫3-模拟用户点击
Python网络爬虫实战2-下载url下的pdf
Python网络爬虫基础1

1.需求背景

针对长虹美菱电器说明书网页形式,编写爬虫代码,要求获取对应型号的pdf。

网站分析:

在这里插入图片描述
第一步:点击一个具体的型号,会打开一个新的pdf的页面,就是目标型号的pdf
第二步:在新的页面点击下载按钮,下载pdf
第三步:切换回原始的型号列表页面
第四步:点击下一页,下载其他型号pdf

2.主要困难与解决方法

上述分析过程有以下需要解决的问题:

问题1. pdf连接不直接暴露。按F12打开开发者模式,我们可以看到,按钮链接时什么也没有的。也就是说不能采用requests获取url的方式,只能通过Selenium模拟用户点击。
在这里插入图片描述
解决1:Selenium模拟用户点击,开发者模式下获取向右箭头的位置。发现第一个的Xpath为:

/html/body/div/div[2]/div/div[3]/ul/li[1]/div/div/span-----第一个
/html/body/div/div[2]/div/div[3]/ul/li[2]/div/div/span-----第二个
.....
/html/body/div/div[2]/div/div[3]/ul/li[9]/div/div/span-----第九个个

每一页有九个,可以使用一个for循环用i变量来循环每个位置:

/html/body/div/div[2]/div/div[3]/ul/li[{i}]/div/div/span
同理,我们也可以得到对应的文字说明位置。
/html/body/div/div[2]/div/div[3]/ul/li[{i}]/div/div/text()

问题2:点击箭头打开新的连接页面,通过 self.driver.switch_to.window(handle),切换窗口,pdf_url = self.driver.current_url得到pdf连接,发现此url,无法通过使用download_file_from_url函数下载pdf。

def download_file_from_url(url, save_path, file_name):
    '''
    url为以.pdf为结尾的链接
    '''
    response = requests.get(url, timeout=10, stream=True, verify=False)
    if response.status_code == 200:
        with open(os.path.join(save_path, file_name), 'wb') as f:
            for chunk in response.iter_content(1024):
                f.write(chunk)
        return True
    else:
        return False

报错如下:

requests.exceptions.SSLError: HTTPSConnectionPool(host=‘mlmall.meiling.com’, port=443): Max retries exceeded with url
通常表示在尝试通过HTTPS(端口443)连接到指定的主机(mlmall.meiling.com)时发生了SSL/TLS相关的问题
可能是SSL证书问题

总之,是无法从url链接下载pdf。还是只能使用模拟用户点击。

在这里插入图片描述
**解决2:**如图所示,找到下载按钮的xapth=//*[@id=“download”] 以此进行定位和点击。

如此便有另一个问题,就是点击此按钮就进行下载pdf了,并不能进行重命名。解决方法只能是将对应的pdf链接和下载的文件及对应的型号信息存储在excel中,爬取完成之后,再根据excel中的信息进行统一的重命名。

问题3:点击下一页
**解决3:**模拟用户点击,获取下一页的按钮,点击它

问题4:如果程序出错停止,如何不重头开始

3.代码实现

1.首先定义一个类,主要是为了更改文件下载的默认地址,和设置全局变量,存储型号文本和pdf链接,以方便存储到excel中

'''
import os
import pandas as pd
import time
import shutil

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options


class MeiLin():

    def __init__(self,
                 url='https://mlmall.meiling.com/meiling/pages/servicesSupport.html?_v=0.1.0#/instructions',
                 cur_page=1,# 记录当前页面
                 ):
        chrome_options = Options()
        prefs = {
            "download.default_directory": "E:\downl",  # 下载文件夹路径
            "download.prompt_for_download": False,
            "download.directory_upgrade": True,
            "safebrowsing.enabled": True
        }
        chrome_options.add_experimental_option("prefs", prefs)

        self.res=[]
        self.driver = webdriver.Chrome(options=chrome_options)
        self.driver.get(url)
     

2.每一页的主要执行流程

    def get_one_page_pdf(self, finish_page=85, page=0):
# finish_page为了指定结束的页面(在实际中发现,到了一定的页面,有的型号不含pdf链接了,新打开的页面结构也不是这样了)
# page 标识正在处理的页面
        try:
            while(page<finish_page+1):
                # 到了指定的页面进行下载
                # if page>2:
                #    break
                page += 1
                if page < 4:
                # 发现前3页,点击下一页的按钮和之后的不一样,所以这里进行分情况,都是实战找出的啊
                # 为了偷懒就这样吧,实现功能但并不优雅
                    button_xpath = '/html/body/div/div[2]/div/div[3]/nav/ul/li[8]/a'
                else:
                    button_xpath = '/html/body/div/div[2]/div/div[3]/nav/ul/li[9]/a'

                # 每页有9个说明书
                for i in range(1, 10):
                    one_mes = []
                    #if i > 1:
                     #   break
                    try:
                        # 获取型号文本
                        text_xpath = '/html/body/div/div[2]/div/div[3]/ul/li[{}]/div/div'.format(i)
                        text = self.driver.find_element_by_xpath(text_xpath).text

                        one_mes.append(text)

                        # 点击一个具体的型号,打开了一个新的链接
                        xpath = '/html/body/div/div[2]/div/div[3]/ul/li[{}]/div/div/span'.format(i)
                        click_element = WebDriverWait(self.driver, 5).until(
                            EC.element_to_be_clickable((By.XPATH, xpath))
                        )
                        click_element.click()
                        
                        # 记录当前主要页面的句柄
                        base_window = self.driver.current_window_handle

                        all_handles = self.driver.window_handles
                        for handle in all_handles:
                            if handle != self.driver.current_window_handle:
                                # 找到了新打开的页面,切换到新页面,得到url
                                self.driver.switch_to.window(handle)
                                pdf_url = self.driver.current_url

                                # 有的不是pdf链接,进行后缀判断
                                if '.pdf' in str(pdf_url):
                                    one_mes.append(pdf_url)
                                    time.sleep(10)
                                
                                    # 进行pdf下载
                                    try:
                                        click_element = WebDriverWait(self.driver, 5).until(
                                            EC.element_to_be_clickable((By.XPATH, '//*[@id="download"]'))
                                        )
                                        click_element.click()
                                        time.sleep(10)

                                    except:
                                        print("第{}页的第{}个不是pdf网页,保存失败".format(page, i))
                                        pass

                        print("完成第{}页的第{}个".format(page, i))
                        self.res.append(one_mes)

                        self.driver.close()
                    except:
                        print("第{}页的第{}个操作失败".format(page, i))
                        # 如果失败了,还切回去原来的窗口,重新开始
                        self.driver.switch_to.window(base_window)
                        continue

                    # 完成,关闭该页面,切换到原始窗口
                    self.driver.switch_to.window(base_window)

                print("已经完成第{}页".format(page))
                
                # 点击下一页,进行下一页的下载
                try:
                    click_element = WebDriverWait(self.driver, 5).until(
                        EC.element_to_be_clickable((By.XPATH, button_xpath))
                    )
                    click_element.click()
                    time.sleep(3)
                except:
                    print("无法点击下一页")
                    break
        except:
            print("while 循环终止")


3.程序入口:



if __name__=="__main__":
    meilin = MeiLin()
    
    try:
        
        meilin.get_one_page_pdf(finish_page=85)
    except:
        pass
        
    finally:
        data = meilin.res
        df = pd.DataFrame(data, columns=['电器型号', '说明书链接'])
        save_folder = 'E:\\HWR_files\\Pycharm_files\\HWR\\webcraw\\美菱.xlsx'
        df.to_excel(save_folder, index=False, sheet_name='匹配结果')

    print("------------------保存完成------------------")


结果图:(只取了两页,每页取一个)
在这里插入图片描述

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

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

相关文章

数通云网架构师涨薪班毕业都有哪些工作企业和岗位?

数通云网架构师涨薪班课程学完后&#xff0c;学员具备全行业全场景交付数通项目的能力&#xff0c;胜任企业网&#xff0c;广域网&#xff0c;数据中心网络等各种网络项目的交付能力&#xff0c;技术能力一项能够匹配年薪达30w-40w以上网络工程师岗位。 与誉天进行人才培养&…

Swagger2及常用校验注释说明

Api(value "后台用户管理") RestController RequestMapping("bossuser") public class BossUserController {ApiOperation(value "测试接口")PostMapping("test")public String testUser(Valid RequestBody TestUser user) {LOG.inf…

大数据------额外软件、插件及技术------Linux(完整知识点汇总)

Linxu 不同领域的主流操作系统 桌面操作系统 WindowsMAac OSLinux 服务器端操作系统 UNIX&#xff08;付费&#xff09;LinuxWindows Server&#xff08;付费&#xff09; 移动设备操作系统 Android&#xff08;基于Linux开源&#xff09;IOS&#xff08;不开源&#xff09; 嵌…

电脑桌面便签怎么添加,桌面备忘录软件哪个简单又好用?

在日常的工作或学习中&#xff0c;我们经常需要记事、备忘。这时&#xff0c;一个简单实用的桌面便签工具就显得尤为重要了。那么&#xff0c;电脑桌面便签怎么添加&#xff1f;又有哪些桌面备忘录软件既简单又好用呢&#xff1f; 首先&#xff0c;关于如何添加电脑桌面便签。…

vue如何引入图标

方法1&#xff1a;iconify/vue pnpm add iconify/vue -D 网址&#xff1a;https://icon-sets.iconify.design/ 使用哪个需要安装 如下截图,安装指令&#xff1a; > npm install iconify/icons-gg在使用的页面引入 import { Icon } from “iconify/vue”; <template>…

CODESYS+EtherCAT+X86/ARM硬件平台:高性能运动控制的标配,支持定制

支持的硬件标准与定制平台&#xff1a; X86:INTEL ARM: RK3568/RK3588/TI/NXP/树莓派/全志T3/A40i等 前段时间分享了施耐德基于CODEYS开发的首款支持EtherCAT总线的运动控制器&#xff0c;CODESYSEtherCATX86硬件平台&#xff1a;高性能运动控制的标配。 CODESYS第一次接触还…

【银河麒麟】unzip程序卡住,处理机制详解,附代码

1.服务器环境以及配置 【机型】 处理器&#xff1a; HUAWEI,Kunpeng 920 内存&#xff1a; 400G 【内核版本】 4.19.90-23.18.v2101.ky10.aarch64 【OS镜像版本】 银河麒麟高级服务器操作系统V10-SP1-0711-arm 【第三方软件】 docker 2.问题现象描述 一台k8s服务器…

Camera2内存泄漏修复

最近公司想要使用Camera2来替换线上的旧版相机&#xff0c;功能调研过程中发现Camera2在很多机器上都会有奇怪的内存泄漏&#xff0c;比较明显的时候可能有100M&#xff0c;比较常见的是表现为内存释放不及时&#xff08;上涨一段时间后会有一次下降&#xff09;&#xff0c;这…

Web渗透:XXE-XML外部实体漏洞

XML External Entity (XXE) 漏洞是一种注入攻击&#xff0c;利用不安全的XML解析器来执行各种恶意操作&#xff0c;如读取本地文件、执行远程代码、发起拒绝服务攻击等&#xff1b;此漏洞的根本原因在于XML标准允许在文档中定义外部实体&#xff0c;并在解析时进行解析和替换。…

快储存,分布式文件系统,对象储存

Ceph块存储 镜像快照 快照可以保存某一时间点时的状态数据快照是映像在特定时间点的只读逻辑副本希望回到以前的一个状态&#xff0c;可以恢复快照使用镜像、快照综合示例 rbd create img1 --size 10G 创建镜像rbd ls 查看镜像 rbd info img1 #查看…

使用原子子表创建可重用的子组件

原子子表是一个图形对象&#xff0c;可帮助您在Stateflow图表中创建独立的子部件。原子子表允许&#xff1a; 对具有多个状态或层次结构的图表进行微小更改后&#xff0c;模拟速度更快。 在多个图表和模型中重复使用相同的状态或子表。 易于团队开发&#xff0c;适用于在同一图…

大语言模型在医疗领域的进展、应用和挑战_医疗大语言模型算法csdn

### 概述 本文综述了医学领域大型语言模型&#xff08;LLM&#xff09;的进展、应用和面临的挑战。大型语言模型如ChatGPT在理解和生成人类语言方面显示出了显著的能力&#xff0c;引起了广泛关注。在医学领域&#xff0c;研究人员正致力于利用LLM支持各种医疗任务&#xff0c…

文华财经盘立方博易大师主图指标公式大全源码均线

文华财经盘立方博易大师主图指标公式大全源码均线&#xff1a; N:3; EMA25:EMA(C,25),COLORRED,LINETHICK2; EMA70:EMA(C,70),COLORGREEN,LINETHICK2; EMA450:EMA(C,450),COLORYELLOW,LINETHICK2; CONDA1:EMA25>EMA70&&C>HV(H,6)&&C>EMA450&…

C语言 | Leetcode C语言题解之第179题最大数

题目&#xff1a; 题解&#xff1a; long cmp(int *x, int *y) {unsigned long sx 10, sy 10;while (sx < *x) {sx * 10;}while (sy < *y) {sy * 10;}return sx * (*y) (*x) - sy * (*x) - (*y); }char *largestNumber(int *nums, int numsSize) {qsort(nums, numsSi…

Linux C 程序 【01】最小程序

1.开发背景 基于 RK3568 平台的基础上&#xff0c;编译一个在系统上运行的最小程序。 2.开发需求 由于 RK3568 作为宿主机&#xff0c;在上面编译程序比较慢&#xff0c;所以还是采用在 Ubuntu 下交叉编译后再拷贝到宿主机上运行。 设计实验&#xff1a; 1&#xff09;搭建 M…

数据分析必备:一步步教你如何用matplotlib做数据可视化(14)

1、Matplotlib 图像 Matplotlib包中的图像模块提供加载&#xff0c;重新缩放和显示图像所需的功能。Pillow库支持加载图像数据。Matplotlib仅支持PNG图像。如果本机读取失败&#xff0c;下面显示的命令将回退到Pillow。 此示例中使用的图像是PNG文件&#xff0c;但请记住数据的…

AFLNet入门教学——测试RTSP协议实现Live555(Ubuntu)

1、简介 本文旨在使用AFLNet对RTSP协议实现Live555进行模糊测试。实验环境为&#xff1a;Ubuntu22.04.4AFLNet安装参考&#xff1a;AFLNet入门教学——安装&#xff08;Ubuntu22.04.4&#xff09;-CSDN博客 2、安装Live555 本次实验采取的是live555在2018年8月28日上传的版本…

数据库怎么同步

数据库要怎么同步呢&#xff0c;有很多方法&#xff0c;看你用什么数据库&#xff0c;如果是Sqlserver,你要数据库同步&#xff0c;那么可以使用自带的订阅发布&#xff0c;订阅发布应该是不错的方法&#xff0c;但是我上次要配置双向同步&#xff0c;它的对等发布好像没部署成…

【LeetCode】四、栈相关:有效的括号 + 下一个更大的元素

文章目录 1、栈结构2、Java中的栈3、leetcode20&#xff1a;有效的括号4、leetcode496&#xff1a;下一个更大元素 1、栈结构 和队列相反&#xff0c;栈先进后出 时间复杂度&#xff1a;访问、插入、删除都在栈顶进行操作&#xff0c;时间复杂度为O(1)&#xff0c;搜索需要遍…

【自监督-MIM】系列方法学习二

Masked image modeling 是一种训练深度学习模型的技术,尤其是在视觉领域,类似于自然语言处理中的掩码语言建模(Masked Language Modeling)。它通过在输入图像中随机遮挡(或称为掩码)部分区域,然后训练模型来预测这些被遮挡部分的内容,从而提高模型的视觉理解能力。 Ma…