【Day28-爬虫】资料分析有时候还是需要自己生资料的——以python自动抓取gif梗图为例,十分钟简单上手爬虫(含范例程序)

在我们学习资料分析的过程中,很常会被拿到各种各样的资料集来作为例子,不过有的时候我们也会希望有一些比较不同或是比较实际特定遇到的资料来进行分析,那这个时候具备有自己可以获得资料的能力就很方便了,因此今天会来简单介绍一下基本的爬虫概念,并以自动爬取一个gif梗图网站的梗图下载下来为例子吧(私心XD)

网页是什麽?

网页,一个对我们日常生活中非常熟悉的东西(还是其实现在年轻人都只用app了吗?)
不论是用来看新闻、看股票,亦或是拿来看梗图都非常的方便,而这也自然成为了一个很适合作为资料分析来源的地方,不然每次都用那种竞赛或是实验室所提供的资料不觉得有点无趣吗~

那网页是什麽呢

网页其实和程序一样,就只是一堆文字而已

不过就像不同的程序语言有不同的语法,网页页面实际上也是遵循着特定的规则来记录的内容,一般都是遵循 html(HyperText Markup Language) 的形式来记录内容。

我们用浏览器看到了什麽?

以我今天打开一个梗图网站为例,我看到了不同的区块、文字、影片、连结...等内容,而这些内容又有着不同的样子(例如不同的字体大小)或是不同的功能(例如某区块点了之後会跳转),那这些其实都是依靠我们的浏览器帮我们把网站的html内容解析之後转换成适合人类阅读和操作的样子。

浏览器看到了什麽?

那既然我们说网页只是一串文字,那要怎麽看到这串文字长得怎样呢?

检视网页原始码

我们只要在网页的空白处按下「检视网页原始码」(Chrome)或是「检视页面来源」(Edge)就可以看到这个页面的原始html是长得怎样了。

使用浏览器工具检查元素

那既然我们不是电脑,在没有什麽经验的时候面对这麽大量的原始码内容当然会不太方便,所以这个时候可以使用浏览器内建的开发工具来直接找到某个页面元素相关的html内容。

左边的页面会随着我们右边滑鼠指到不同的区块而产生对应的高亮以方便我们检视。

网页基本元素

对於第一次接触到网页架构的读者也许会觉得它好像很复杂,不过我们作为一个只是要它的资料而不是要知道它是怎麽建立起来的角度,我们只需要知道

网页元素,就是一堆<类型 一些属性>一些内容</类型>的东西包来包去而已

像是这边的gif,我们发现他的元素内容是

<video autoplay="" muted="" loop="" poster="https://media.giphy.com/media/W0yN0GEVU2eHUeYlYQ/giphy.gif">
<source src="https://media.giphy.com/media/W0yN0GEVU2eHUeYlYQ/giphy.mp4" type="video/mp4">
</video>

因此它看起来就是一个有一些各种(不用管)属性的video而已

爬虫是什麽?

说完网页的基本架构,那来讲一下爬虫的定位

用程序代替我们和浏览器

爬虫其实就是用各种语言的程序来代替我们和浏览器,用来取得网页的内容
而同时因为程序很适合处理大量的资料,因此拿来做一些自动化的操作就很方便
我们这边以python中最基本的request套件来说明要如何取得网页

import requests
url = "https://www.gif-vif.com/you-are-a-wizard-doggo"
res = requests.get(url) # 取得回应
res

输出:

<Response [200]> 

这边的200表示正常收到内容,而如果是

  • 4xx:通常表示是使用者端有某些问题导致没正常收到内容
  • 5xx:通常表示是服务器那边的问题而传不出内容

那既然爬虫是代替浏览器,我们刚刚看到的原始码又在哪边呢?

# 显示原始码
print(res.text)

那我们有了原始码之後,可是我们不像是在用浏览器一样有滑鼠可以去选择,那要如何找到这些资料呢?

要怎麽找到特定的资料?

如果你想到的是可以用我们之前讲过的字串处理技巧和正规搜寻的话,那先很感谢你有认真在看我这写的不是很精练的文字。但其实既然爬虫资料处理是一个很基本的需求的话,那通常python就会有对应的套件,我们这边以最常见的BeautifulSoup为例子

人生苦短,我用python
——某位大前辈

使用BeautifulSoup解析原始码

from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, 'lxml') # lxml是解析方式
soup

找出所有video元素

vidio_elements = soup.find_all("video")
vidio_elements

那发现我们所需要的gif连结就在这个地方,因此剩下就是把它取出来

一层一层往下取出需要的东西

gif_url = vidio_elements[0].get("poster")
gif_url

输出:

'https://media.giphy.com/media/W0yN0GEVU2eHUeYlYQ/giphy.gif'

根据gif元素网址下载档案

gif = requests.get(gif_url) # 一样再取得一次网页
with open("sample.gif", "wb") as f: # 用二进制方式写入档案
    f.write(gif.content) # content表示内容

那执行之後应该就会看到它在这份程序的同一个资料夹了

要如何自动化下载?

我们可以用同样的原理,将下一页的url也取出来,然後重复呼叫就可以自动下载档案了~

def get_gif(url):
    title = url.split("/")[-1] # 取得url结尾作为标题
    print(f"getting gif {title}")
    res = requests.get(url) # 取得回应
    
    # 使用BeautifulSoup解析内容
    soup = BeautifulSoup(res.text, 'lxml')
    vidio_elements = soup.find_all("video")
    gif_url = vidio_elements[0].get("poster")

    # 下载gif
    gif = requests.get(gif_url)
    with open(f"{title}.gif", "wb") as f:
        f.write(gif.content)
    
    # 寻找下一个url
    next_url = soup.find(id="share_and_next").find_all("a")[-1].get("href")
    
    return next_url


if __name__ == "__main__":
    url = "https://www.gif-vif.com/you-are-a-wizard-doggo"
    for i in range(10):
        url = get_gif(url)

好几天没有打的这麽长了,因为想说只提最基本必要的东西,但又想举个实际的例子所以还是会有一点不同的步骤要说明。不过如果这边的可以看懂之後,再配合一点基本的html不同元素的知识,应该就可以做出一些非常基本的爬虫了~


<<:  Re: 新手让网页 act 起来: Day28 - Error boundary

>>:  开源网路钓鱼框架-Gophish(补充)

TailwindCSS 从零开始 - 简单认识 PostCSS

前面有提到安装 TailwindCSS 推荐使用 PostCSS,前面练习的都是没有相依 Post...

使用Raspberry pi的相机拍图

前面只用linux 的指令来拍图 现在用Python了 from time import sleep...

Day20 X CDN

CDN 这个名词在前面的篇章应该出现过蛮多次的,一直感到困惑的朋友们不用担心,今天终於要来好好介绍...

Day1 用 Next.js 拆分 WordPress 前端 - 系列简介

哈罗,我是Eason,欢迎来到我的 「WordPress 再进化,用 Next.js 拆分前端,实现...

Day 29 - Vanilla JS Countdown Timer

前言 JS 30 是由加拿大的全端工程师 Wes Bos 免费提供的 JavaScript 简单应用...