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

【前期提要】感兴趣的可以看看往期文章哈~
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("------------------保存完成------------------")


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

  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
网络爬虫是指通过网络技术自动化地抓取互联网上的信息,常见的应用包括数据采集、搜索引擎、价格比较、舆情监控等。Python是一种非常适合用于编写网络爬虫的编程语言,因为它具有简单易学、语法清晰、强大的第三方库等优点。 下面是一个简单的Python网络爬虫实战示例,它可以爬取指定网站的所有图片并保存到本地: ```python import requests from bs4 import BeautifulSoup import os url = 'https://www.example.com' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} response = requests.get(url, headers=headers) soup = BeautifulSoup(response.text, 'html.parser') img_folder = 'images' if not os.path.exists(img_folder): os.makedirs(img_folder) for img in soup.find_all('img'): img_url = img.get('src') if not img_url.startswith('http'): img_url = url + img_url img_name = img_url.split('/')[-1] img_path = os.path.join(img_folder, img_name) with open(img_path, 'wb') as f: f.write(requests.get(img_url).content) print('Saved:', img_path) ``` 这个示例中,我们使用requests库发送HTTP请求获取网页内容,使用BeautifulSoup库解析网页HTML代码,然后遍历所有图片标签,获取图片URL并下载保存到本地。同时,为了防止被网站屏蔽,我们设置了User-Agent请求头伪装成浏览器访问网站。 当然,网络爬虫还有很多其他的应用和技术,例如反爬虫机制、代理IP、分布式爬虫等。这些都需要具备一定的编程和网络知识,同时也需要遵守相关的法律和道德规范。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值