• Pyppetter结合beautifulSoup爬虫定位支付宝SDK和华为SDK更新的最新版本


    BUG

    soup = BeautifulSoup(rep,"lxml")报错bs4.FeatureNotFound: Couldn’t find a tree builder with the features you requested: html_parser.

    解决方案:安装lxml

    第一步是建立BeautifulSoup对象,这个对象在bs4模块中。在建立对象的时候可以额外指定一个参数,作为实际的HTML解析器。解析器的值可以指定html.parser,这是内置的HTML解析器。更好的选择是使用lxml解析器,纯C语言实现,速度会更快。如果使用lxml需要安装lxml包,不然会报上面的错误。

    selenium和requests爬虫
    1. Selenium,实际是一个自动化测试工具,现在已经被广泛用于网络爬虫中来应对 JavaScript 渲染的页面的抓取,但是需要安装浏览器驱动,通过浏览器驱动来定位网页元素
    2. requests,python的第三方包,可以发起post、get、put、delete等请求,可以用于自动化接口测试,但是使用requests的get方法只能获取静态网页,一些使用js代码渲染的页面无法抓取
    Pyppeteer

    鉴于上述两种方法的缺点,采用pyppeteer进行抓包,是 Puppeteer 的 Python 版本的实现,由一位来自于日本的工程师依据 Puppeteer 的一些功能开发出来的非官方版本。 在 Pyppetter 中,实际上它背后也是有一个类似 Chrome 浏览器的 Chromium 浏览器在执行一些动作进行网页渲染。Chromium 是谷歌为了研发 Chrome 而启动的项目,是完全开源的。二者基于相同的源代码构建,Chrome 所有的新功能都会先在 Chromium 上实现,待验证稳定后才会移植,因此 Chromium 的版本更新频率更高,也会包含很多新的功能,但作为一款独立的浏览器,Chromium 的用户群体要小众得多。两款浏览器 “同根同源”,它们有着同样的 Logo,但配色不同,Chrome 由蓝红绿黄四种颜色组成,而 Chromium 由不同深度的蓝色构成。参考链接

    from pyppeteer import launch
    
    def crawl(url):
        browser = await launch(options={'args': ['--no-sandbox']})  # 创建浏览器对象
        page = await browser.newPage()   #新建标签页
        await page.goto(url,{'timeout': 1000*60})  #根据url获取页面相应内容
        rep = await page.content()  # 爬取整个网页数据
    		print(rep)  #打印出来的就是一个HTML
        await browser.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    Beautiful Soup4

    使用Beautiful Soup4定位网页元素,方便我们获取想要的信息,后面简称bs4。

    主要用到bs4的两个函数,一个find会找到出现的首个满足条件的元素;findAll找到所有满足条件的元素。在实际应用中可以灵活运用。这两个函数可以只传一个参数如soup.find(‘title’),即找到rep中的title标签。但是对于一些标签有多个,比如ul有两个的情况下,可以荣归class加以区分,即soup.find(‘ul’,class_=“list1”)即可定位到第一个ul。

    1. 对于具有唯一性且没有嵌套的标签,如title标签,可以直接通过soup.title.string直接获取文本“Testing”
    2. 对于有嵌套的标签,如h2,可以通过soup.h2.get_text()获取文本内容“I am embbed"
      • 这里标签名是否唯一只会影响我们是否取到想要的信息,但是程序是可以正常运行输出的
      • 如果标签名唯一就输出文本内容,如果不唯一,就输出第一个h2标签的文本内容
    3. 标签名不唯一文本内容获取,以li标签举例
      • 在rep中,虽然li有多个,但是我们可以根据ul缩小范围,soup.find('ul',class_="list1").findAll('li')这样我们可以得到list1下的两个li标签。想进一步获取特定li标签的内容,如果有可以唯一标识的,就在find参数里加上唯一属性;如果没有,也可以按照在列表中的相对位置,通过索引获取文本内容。
    from bs4 import BeautifulSoup
    
    
    rep = '''Testing
    
    		

    I am embbed ...

    • 列表1第1项
    • 列表1第2项

    文字1

    文字2

    • 列表2第1项
    • 列表2第2项
    ''' def bs4_use(url): soup = BeautifulSoup(rep, "lxml") #创建一个beautiful soup对象,html解释器选择lxml,req为爬取的网页信息 #soup = BeautifulSoup(open("index.html"), "lxml") #打开本地html文件创建bs4对象 print(soup.title) print(soup.find('title').get_text())
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    以支付宝SDK最新版本定位举例

    查看元素标签、位置

    首先我们通过检查,先查看需要定位内容在HTML中的标签属性,相对位置,可以看到

    1. 版本号是一个h3标签,这个id虽然是唯一的,但是如果SDK更新,那最新版本的id一定会发生改变,所以打消用id直接定位。
    2. 版本号下面跟着三个p标签,p标签的内容有更新日期,以及提升的内容,这里有两个一个是大体的描述那方便改进了,一个描述的是具体的更新信息
      • 这里需要注意一下,是不是每个更新的版本信息里都会有两种描述,后面发现有的版本没有大致描述,只有一个详细描述,也就是在h3标签下只有两个p标签,所以后面取数据的时候需要注意。

    在这里插入图片描述

    无法ID定位时查看网页整体布局

    上面分析,根据ID定位元素代码复用性几乎是0,所以我们需要看网页的整体布局,下图中左边是源码,右边是页面布局,可以看到不同版本其实是依次排序的,即一个h3后面2-3个p标签为一个版本,后面又是一个h3标签接2-3个p标签。。依次直到所有的版本列举完。这些不同的版本中有着异同点,可以根据异同点来定位。

    1. 相同点:每个版本的第一个p标签是更新日期,且标签的文本内容一定包含“更新日期:”这五个字符,注意冒号是中文冒号
    2. 不同点:每个版本号不同;更新信息描述不同,15.8.08更新信息只有详细信息
      在这里插入图片描述
    实现

    安装包:bs4、pyppeteer

    版本号:因为最新版本一定是在最上面,所以我们找到的第一个h3标签就是最新版本的版本号。(这里的前提是前面没有出现h3标签)

    其他信息

    1. 都是在p标签,所以我们可以直接找到所有的p标签,保存在列表中。遍历所有p标签,出现的第一个包含“更新日期”的p标签即最新版本的更新日期时间,停止遍历,同时记录一下索引index
    2. 由于我们不确定后面的更新信息是只有一个还有两个,所以我们可以找到第二个版本的更新日期,第二个版本的更新日期的前一个p标签一定是更新的详细信息
    3. 从index+1开始遍历,最多遍历3个p标签,一定可以到第二新版本的更新日期,记录第二新版本更新日期的p标签索引i,那么最新版本的更新信息在列表中的索引即为i-1
    4. 至此既可获取最新版本号、更新日期、更新详细信息。
      • 在获取更新日期时,可以使用字符串切片,使用中文冒号作为分隔符,即可获取2022-04-21
    import asyncio
    from pyppeteer import launch
    from bs4 import BeautifulSoup
    
    
    async def main(url):
        browser = await launch(options={'args': ['--no-sandbox']})  # 使用pyppeteer静态/动态网页都可成功爬取
        page = await browser.newPage()
        await page.goto(url,{'timeout': 1000*60})
        await asyncio.sleep(15)
    
        rep = await page.content()  # 爬取到整个网页数据,接下来可用 正则/BeautifulSoup 就可以抓取数据
        soup = BeautifulSoup(rep, "lxml")
        latest_version = soup.h3.get_text()
        other_msg = soup.findAll('p')
        #find the latest update date
        for index,item in enumerate(other_msg):
            if '更新日期' in item.get_text():
                date = item.get_text().split(':')[-1]
                break
        #find the second update date and locate the uopdated meaasge of the latest version
        for i in range(index+1,index+4):
            if '更新日期' in other_msg[i].get_text():
                break
        update_msg = other_msg[i-1].get_text()
        print(latest_version)
        print(date)
        print(update_msg)
        await browser.close()
    
    
    if __name__ == '__main__':
        url = 'https://opendocs.alipay.com/open/02no45'  # 爬取的网址
        asyncio.get_event_loop().run_until_complete(main(url))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  • 相关阅读:
    Vivado从此开始(进阶篇)读书笔记——综合阶段相关知识点
    如何对需求变更进行精准的风险评估?
    ubuntu22.04 在wifi网络正常使用的情况下创建热点连接
    jQuery特效
    分享Figma一些非常快速、省时、省力的功能和小技巧
    攻防演练中防守方的防护措施.
    提高效率的vscode插件推荐
    6、Linux:一起玩转vi/vim编辑命令
    MySQL-事务操作
    Ubuntu 20.04 下DeepSDF环境配置笔记
  • 原文地址:https://blog.csdn.net/weixin_42486554/article/details/126248739