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()
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 = '''<title>Testing</title>
<body>
		<h2>I am embbed
		<tr>...</tr>
		</h2>
    <ul class='list1'>
        <li>列表1第1项</li>
        <li>列表1第2项</li>
    </ul>
    <p class='first'>文字1</p>
    <p class='second'>文字2</p>
    <ul class='list2'>
        <li>列表2第1项</li>
        <li>列表2第2项</li>
    </ul>
</body>'''

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())
以支付宝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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秃头嘤嘤魔

感谢厚爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值