zoukankan      html  css  js  c++  java
  • 分享一个零基础快速爬取数据的工具

    今天介绍下如何使用pyppeteer抓取网页的数据。pyppeteer是web应用自动化测试的具,可以直接运行在浏览器中,通过代码控制与页面上元素进行交互,并获取对应的信息。

    以前我们我们爬取数据都是通过写代码爬取,当待爬取的网站需要登录时,我们需要在代码中模拟登录;当爬取过快需要验证时,我们需要在代码中实现验证逻辑;当ip被封时,还需要有自己的动态ip库。待爬网站的反爬策略越多,我们爬取的成本就越大。总之,用写代码的方式爬取数据需要构造比较复杂的请求,想尽一切办法将爬虫伪装成真实的用户。

    使用pyppeteer这样的工具,就可以在很大程度上解决上面的问题。同时,还有一个优点是所见即所得,不需要再去研究网页复杂的请求结构。当然这类工具也是优缺点的,它增加了你去理解网页上各种元素以及交互的成本。所以我觉得这类工具最适合在短平快的爬虫场景中使用。比如我在最近的工作中就遇到两次这样的情况,想爬一些特别简单的数据来提升工作效率,但又不想研究网页是如何构造请求的,用这种所见即所得的工具就可以快速抓取想要的数据。

    下面我们以“抓取百度搜索数据”例子我介绍一下pyppeteer的使用。正式介绍前我们先来看下爬取效果:

    安装pyppeteer

    python3 -m pip install pyppeteer
    

    安装完成后,执行pyppeteer-install命令安装最新版本的 Chromium 浏览器。根据官方文档的说明,安装pyppeteer需要Python3.6以上的版本。

    由于pyppeteer是基于asyncio实现的,所以我们的代码中也会用async/await来写代码,之前没写过的朋友也不用担心,基本不影响对pyppeteer的使用,有必要的话以后再单独写篇文章介绍。

    首先,用pyppeteer启动 chrome 进程

    from pyppeteer import launch
    # headless 显示浏览器
    # --window-size 设置窗体大小
    browser = await launch({'headless': False,
                            'args': ['--window-size=%d,%d' % (width, height)]
                            })
    

    然后,打开一个新的标签,并访问百度

    # 打开新页面
    page = await browser.newPage()  
    # 设置内容显示大小
    await page.setViewport({"width": width, "height": height})  
    # 访问百度
    await page.goto('https://www.baidu.com')  
    

    打开百度网站后,下一步就要向搜索输入框输入内容,首先要找到输入框的html标签 从上图可以看到,<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">代码代表搜索输入框,该标签的 class 是s_ipt,那下面我们就通过type函数找到该标签,并键入需要搜索的内容

    # 将对应的 selector 填入 python,通过.s_ipt找到输入框html标签
    await page.type('.s_ipt', 'python')
    

    这里我们搜的是python,有了输入后就可以点击“百度一下”按钮来发起搜索。找按钮的方式与上面一样 可以看到<input type="submit" id="su" value="百度一下" class="bg s_btn">代码代表“百度一下”的按钮,该标签的 id 是su,下面就调用click函数找到该标签,并点击

    # 通过#su找到“百度一下”按钮html标签
    await page.click('#su')
    

    这里需要注意su前面是#而不是.,因为在html标签中它用id表示而不是class,这里涉及html selector的内容,不清楚的朋友可以简单补一下。

    执行完上面的代码,我们可以看到搜索结果了,调用screenshot方法将当前页面保存

    await page.screenshot({'path': 'example.png'})
    

    效果如下: 接下来我们就获取网页内容,并解析每条结果

    # 获取网页内容
    content = await page.content()
    # 解析
    output_search_result(content)
    

    通过BeatifulSoup解析每条结果的标题与链接

    def output_search_result(html):
        search_bs = BeautifulSoup(html, 'lxml')
    
        all_result = search_bs.find_all("div", {'class': "result c-container"})
        for single_res in all_result:
            title_bs = single_res.find("a")
            title_url = title_bs.get('href')
            title_txt = title_bs.get_text()
    
            print(title_txt, title_url)
    

    输出的内容如下

    python官方网站 - Welcome to Python.org http://www.baidu.com/link?url=OqtoElo8HW1GdOgAlqdCTz2lpewFLf0HlbnGdyAKD06BfPbw0fsJ_N5fclxx-q1D
    Python 基础教程 | 菜鸟教程 http://www.baidu.com/link?url=IooFgJjdec1qPXhGhF7tur-z2Qt_43RkK3L-9cp8oB-0i2w7unKzLayLjg3zSQeKQieA49JFejMjqTM-TSY3V_
    Python3 * 和 ** 运算符_python_极客点儿-CSDN博客 http://www.baidu.com/link?url=H3VdAQRAbTkN9jGJGkvhIFTdg48O-b5yib7vCquWyg1-6FZwBVHnJ5iiUYQkjbf-8IuLfOwDXoUMDOdMvXNHkzejts4uRHrczgQqekgQuFy
    Python教程 - 廖雪峰的官方网站 http://www.baidu.com/link?url=piu0nEfXNvkLhWchcdX2EjJvIkQ5beq2_uYH_B7u2vjYO82BZwr8SXgDxnVLZYgGL8xuR_ovjg2cAYfPS9AmLtqUQP-TrWuJWHNqYbxdQnUPTy_VPp8sSBdCaYBl9YDX
    Python3 教程 | 菜鸟教程 http://www.baidu.com/link?url=bx1rMrzxC69Sp0zY08-VhFs40QQ8UFxZdvmZVFcKYkCG2mdojhAMjk5ulKBKwQm77x8vMyOeowW_bNtoP35m3q
    你都用 Python 来做什么? - 知乎 http://www.baidu.com/link?url=YTMr1ycFjtkWx8lgJ_PT3-kF50vYI6Yibh4o69WL_afBSOkkZmGxexxIKXY3fGAX8X2-AaFbI4jL1vJbKMJrsK
    Python基础教程,Python入门教程(非常详细) http://www.baidu.com/link?url=elAepKY7rhULzTPuwKvk8Cxx21K5D0Ey7-Wj9TZgN49MyasPOXtLYfWbp46QZQie
    

    这样,我们的抓取数据的目的已经达到了,当然我们还可以继续拓展下,多用用pyppeteer,比如:我们可以点击下一页,抓取下一页的内容

    # next page
    # 为了点击“下一页”,需要将当前页面滑到底部
    dimensions = await page.evaluate('window.scrollTo(0, window.innerHeight)')
    # 点击“下一页”按钮
    await page.click('.n')
    # 获取第二页的内容
    content = await page.content()
    # 解析
    output_search_result(content)
    

    操作与之前类似,注释写的也比较清楚,我就不再赘述了。最后可以调用await browser.close()代码关闭浏览器。上述代码可以定义需要定义在一个async函数中,如:

    async def main():
      # ... 抓取代码
    

    然后通过下面代码

    asyncio.get_event_loop().run_until_complete(main())
    

    调用main函数。

    pyppeteer的用法就介绍到这里了,类似的工具还有很多,比如:Selenium,我也试了下,确实如网上所说配置上面需要花些功夫,有兴趣的朋友可以自行尝试。希望今天的内容对你有用。关注公众号回复关键字 爬虫 获取完整源码

    欢迎公众号「渡码」,输出别地儿看不到的干货。

  • 相关阅读:
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    8.4 确定两个日期之间的月份数或年数
    (Java实现) 洛谷 P1553 数字反转(升级版)
  • 原文地址:https://www.cnblogs.com/duma/p/12907549.html
Copyright © 2011-2022 走看看