51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 280|回复: 1

[转贴] Python 利用Selenium爬取嵌入网页的PDF(web embedded PDF)

[复制链接]
  • TA的每日心情
    无聊
    2024-3-7 09:16
  • 签到天数: 43 天

    连续签到: 2 天

    [LV.5]测试团长

    发表于 2024-2-23 11:38:50 | 显示全部楼层 |阅读模式
    前言:
    在下载欧洲专利局Global Dossier中的专利审查文件时,想到可以利用Python批量下载,省去一些重复劳动的时间。以下载一篇美国专利(US2021036638A1)的审查档案为例,该专利的审查档案地址为:European Patent Register


    探索记录:
    初涉Python,本人是个纯纯的小白,爬虫也是看入门书籍了解到了皮毛😅,因此也是走一步看一步,出现问题自己慢慢在网上找答案。经过大量试错,最终总结了下方的探索历程,要是有大佬能够看出有啥更方便的渠道,还望不吝赐教。


    1.Ajax异步加载应对方式:
    进入审查档案网址European Patent Register,按F12打开开发者工具后,发现文件位置处于<tbody>下的<tr标签中>

    但是采用request+beautifulsoup模块的方式解析网站时,并不能正确地解析出该网站的内容。经过在网上的查找,应该是这个网站采用了Ajax技术异步加载,也就是我们要解析的内容不是网页原本存在的,而是后期加载进网页中的,简单的request+beautifulsoup的组合拳无法解析ajax加载的内容(个人浅薄的理解,英语专业的我也不知道Ajax技术具体是啥,本段解释仅供参考。)


    那么,如何解析Ajax加载的内容呢?又经过查询,Ajax的请求位置可以通过开发者工具中的【网络】查看。实际加载的部分就是下图红框的部分。


    双击打开后,可以看到它请求的网址是:https://register.epo.org/retrievetoc?apn=US.201916968098.A&d-16544-s=0&d-16544-o=1&lng=en

    打开这个网址后,可以看到里面的内容是这样的

    此时我们再用request+beautifulsoup就可以解析这个网站啦。


    2.利用Selenium下载嵌入网页的PDF
    解析网站后,我遇到了第二个问题,即这个网站中的文件链接并不是以'.pdf'结尾的链接,也就是我无法用request.get()的方式来直接访问下载PDF。于是我又进入了疯狂查找相关信息阶段。


    最后,我发现Stack Overflow中有大量的关于此类PDF下载的处理方法,其中大多数都是采用禁用谷歌浏览器的“PDF Viewer”并设置PDF总是在外部打开的方式下载嵌入网页的PDF(web embeded PDF)。于是我也依样画葫芦,照着站内大佬的代码修改了一下(原代码网址:Downloading a PDF using Selenium, Chrome and Python - Stack Overflow)。
    1. from selenium import webdriver
    2. from selenium.webdriver.common.by import By
    3. from selenium.webdriver.chrome.options import Options

    4. def download_pdf(url):
    5.         download_dir=r'文件下载地址'
    6.         chrome_options = Options()
    7.         chrome_options.add_experimental_option('prefs',  {
    8.             "download.default_directory": download_dir,        
    9.             "download.prompt_for_download": False,
    10.             "download.directory_upgrade": True,
    11.             "plugins.always_open_pdf_externally": True        #PDF始终在外部打开
    12.             }
    13.         )
    14.         #chrome_options.add_experimental_option('detach', True)  #webdriver打开浏览器后保持开启,一般用于测试出错用
    15.         driver = webdriver.Chrome(options=chrome_options)
    16.         driver.get(url)

    17. url=r"https://register.epo.org/documentView?number=US.202217672556.A&documentId=LL16AX4LGREENX1"
    18. download_pdf(url)
    复制代码
    运行上述代码后,我得到了如下网页:


    捏麻的这不还是不行嘛。PDF Viewer确实被禁用了,但是没有像我想象的一样PDF文件会直接下载到我指定的文件夹中。当然也有可能是我后面少了一些代码导致没有下载文件。于是我又开始查了。


    3.爬虫之Iframe
    上方网页中我看到了正中间醒目的【打开】按钮,我点击了一下发现直接就开始下载PDF文件了。自然而然我想到能不能用webdriver的click()来触发下载按钮。


    在开发者工具中按钮对应的id是"open-button",于是我写了下方代码:


    1. <font size="3"> driver.find_element(by=By.ID,value='open-button').click()</font>
    复制代码



    结果出现了no such element: Unable to locate element:的报错。


    怎么会事呢?我继续百度一下,然后找到了下面老哥的文章。


    Python Selenium 元素定位正确,但始终报找不到元素错误Message: no such element: Unable to locate element: {“method“:xxx}_番茄Salad的博客-CSDN博客


    大佬文章中提到了iframe,解释说“如果有嵌套的iframe的话,需要一层一层的从主页面逐层进入了。” iframe这不就是我上面网页button标签的父标签名嘛,因此我在代码前加入了大佬提到的driver.switch_to.frame("myIframe")。果然后面的代码顺利运行。至此在欧专局爬取PDF审查档案的目标就算成功了。至于文件命名及遍历下载可以在最初的ajax网页中分析文件名来实现。在此就不赘述了。


    总结:
    首先,是上述代码的汇总:

    1. from selenium import webdriver
    2. from selenium.webdriver.common.by import By
    3. from selenium.webdriver.chrome.options import Options

    4. def download_pdf(url):
    5.         download_dir=r''
    6.         chrome_options = Options()
    7.         chrome_options.add_experimental_option('prefs',  {
    8.             "download.default_directory": download_dir,        
    9.             "download.prompt_for_download": False,
    10.             "download.directory_upgrade": True,
    11.             "plugins.always_open_pdf_externally": True        #PDF始终在外部打开
    12.             }
    13.         )
    14.         chrome_options.add_experimental_option('detach', True)  #webdriver打开浏览器后保持开启
    15.         driver = webdriver.Chrome(options=chrome_options)
    16.         driver.get(url)
    17.         driver.switch_to.frame("myIframe")        #由于PDF始终在外部打开,打开PDF文件地址后不会显示PDF,而会出现“打开”按钮,该按钮在iframe中。本句将driver转到Iframe中
    18.         driver.find_element(by=By.ID,value='open-button').click()        #定位Iframe中的按钮标签,并点击下载
    复制代码

    再叠个甲:本人为Python新手,使用python主要是为了方便个人工作,并不是专业的编程人员。代码编写可能会有形式不规范的地方,望各位观众海涵。


    最后再感谢一下番茄Salad老哥提供的Iframe解决方法。本来是没打算写这种班门弄斧的文章的,但是国内论坛上好像没有免费的对该类问题比较综合的回答,故写了一下,也方便自己日后参考。


    原文链接:https://blog.csdn.net/Gfrwe/article/details/132228578

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-2-26 15:23
  • 签到天数: 54 天

    连续签到: 1 天

    [LV.5]测试团长

    发表于 2024-2-23 12:10:53 | 显示全部楼层
    这样是爬吗,这不是操作UI页面点击下载吗
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-4-13 20:40 , Processed in 0.070715 second(s), 25 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表