前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Python】下载 XKCD 漫画 如何实现教程

【Python】下载 XKCD 漫画 如何实现教程

原创
作者头像
用户7718188
修改2021-10-08 15:39:12
6030
修改2021-10-08 15:39:12
举报
文章被收录于专栏:高级工程司
代码语言:javascript
复制
#! python3
# downloadXkcd.py - Downloads every single XKCD comic.

import requests, os, bs4

url = 'https://xkcd.com' # starting url
os.makedirs('xkcd', exist_ok=True) # store comics in ./xkcd
while not url.endswith('#'):
# TODO: Download the page.

# TODO: Find the URL of the comic image.

# TODO: Download the image.

# TODO: Save the image to ./xkcd

# TODO: Get the Prev button's url.

print('Done')

你会有一个 url 变量,开始的值是'http://x.com',然后反复更新(在一个 for 循环中),变成当前页面的 Prev 链接的 URL。在循环的每一步,你将下载 URL 上 的漫画。如果 URL 以'#'结束,你就知道需要结束循环。 将图像文件下载到当前目录的一个名为 xkcd 的文件夹中。调用 os.makedirs() 函数。确保这个文件夹存在,并且关键字参数 exist_ok=True 在该文件夹已经存在时, 防止该函数抛出异常。剩下的代码只是注释,列出了剩下程序的大纲。

下载网页

我们来实现下载网页的代码。让你的代码看起来像这样:

代码语言:javascript
复制
#! python3
# downloadXkcd.py - Downloads every single XKCD comic.

import requests, os, bs4

url = 'https://xkcd.com' # starting url
os.makedirs('xkcd', exist_ok=True) # store comics in ./xkcd
while not url.endswith('#'):
# Download the page.
print('Downloading page %s...' % url)
res = requests.get(url)
res.raise_for_status()

soup = bs4.BeautifulSoup(res.text)

# TODO: Find the URL of the comic image.

# TODO: Download the image.

# TODO: Save the image to ./xkcd

# TODO: Get the Prev button's url.

print('Done')

首先,打印 url,这样用户就知道程序将要下载哪个 URL。然后利用 requests 模块的 request.get()函数下载它。像以往一样,马上调用 Response对象的 raise_for_status()方法, 如果下载发生问题,就抛出异常,并终止程序。否则,利用下载页面的文本创建一 个 BeautifulSoup 对象。

寻找和下载漫画图像

让你的代码看起来像这样:

代码语言:javascript
复制
#! python3
# downloadXkcd.py - Downloads every single XKCD comic.

import requests, os, bs4

--snip--

# Find the URL of the comic image.
comicElem = soup.select('#comic img')
if comicElem == []:
print('Could not find comic image.')
else:
comicUrl = 'https:' + comicElem[0].get('src')
# Download the image.
print('Downloading iamge %s...' % (comicUrl))
res = requests.get(comicUrl)
res.raise_for_status()

# TODO: Save the image to ./xkcd

# TODO: Get the Prev button's url.

print('Done')

用开发者工具检查 XKCD 主页后,你知道漫画图像的<img>元素是在一个<div>元 素中,它带有的 id 属性设置为 comic。所以选择器'#comic img'将从 BeautifulSoup 对象中选出正确的<img>元素。 有一些 XKCD 页面有特殊的内容,不是一个简单的图像文件。这没问题,跳过它们 就好了。如果选择器没有找到任何元素,那么 soup.select('#comic img')将返回一个空的列 表。出现这种情况时,程序将打印一条错误消息,不下载图像,继续执行。 否则,选择器将返回一个列表,包含一个<img>元素。可以从这个<img>元素中 取得 src 属性,将它传递给 requests.get(),下载这个漫画的图像文件。

保存图像,找到前一张漫画

让你的代码看起来像这样:

代码语言:javascript
复制
#! python3
# downloadXkcd.py - Downloads every single XKCD comic.

import requests, os, bs4

--snip--

# Save the image to ./xkcd
imageFile = open(os.path.join('xkcd', os.path.basename(comicUrl)), 'wb')
for chunk in res.iter_content(100000):
imageFile.write(chunk)

# Get the Prev button's url.
prevLink = soup.select('a[rel="prev"]')[0]
url = 'http://xkcd.com' + prevLink.get('href')

print('Done')

这时,漫画的图像文件保存在变量 res 中。你需要将图像数据写入硬盘的文件。 你需要为本地图像文件准备一个文件名,传递给 open()。comicUrl 的值类似 'http://imgs.xkcd.com/comics/heartbleed_explanation.png'。你可能注意到,它看起来很 像文件路径。实际上,调用 os.path.basename()时传入 comicUrl,它只返回 URL 的 最后部分:'heartbleed_explanation.png'。你可以用它作为文件名,将图像保存到硬 盘。用 os.path.join()连接这个名称和 xkcd 文件夹的名称,这样程序就会在 Windows 下使用倒斜杠(\),在 OS X 和 Linux 下使用斜杠(/)。既然你最后得到了文件名, 就可以调用 open(),用'wb'模式打开一个新文件。 回忆一下本章早些时候,保存利用 Requests 下载的文件时,你需要循环处理 iter_content()方法的返回值。for 循环中的代码将一段图像数据写入文件(每次最多 10 万字节),然后关闭该文件。图像现在保存到硬盘中。 然后,选择器'a[rel="prev"]'识别出rel 属性设置为 prev 的<a>元素,利用这个<a> 元素的 href 属性,取得前一张漫画的 URL,将它保存在 url 中。然后 while 循环针 对这张漫画,再次开始整个下载过程。 这个程序的输出看起来像这样:

Downloading page http://xkcd.com... Downloading image http://imgs.xkcd.com/comics/phone_alarm.png... Downloading page http://xkcd.com/1358/... Downloading image http://imgs.xkcd.com/comics/nro.png... Downloading page http://xkcd.com/1357/... Downloading image http://imgs.xkcd.com/comics/free_speech.png... Downloading page http://xkcd.com/1356/... Downloading image http://imgs.xkcd.com/comics/orbital_mechanics.png... Downloading page http://xkcd.com/1355/... Downloading image http://imgs.xkcd.com/comics/airplane_message.png... Downloading page http://xkcd.com/1354/... Downloading image http://imgs.xkcd.com/comics/heartbleed_explanation.png... --snip-- 这个项目是一个很好的例子,说明程序可以自动顺着链接,从网络上抓取大量 的数据。你可以从 Beautiful Soup 的文档了解它的更多功能:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/#

类似程序的想法

下载页面并追踪链接,是许多网络爬虫程序的基础。类似的程序也可以做下面的事情: • 顺着网站的所有链接,备份整个网站。

• 拷贝一个论坛的所有信息。

• 复制一个在线商店中所有产品的目录。

requests 和 BeautifulSoup 模块很了不起,只要你能弄清楚需要传递给 requests.get() 的 URL。但是,有时候这并不容易找到。或者,你希望编程浏览的网站可能要求你先 登录。selenium 模块将让你的程序具有执行这种复杂任务的能力。

完整代码

代码语言:javascript
复制
#! python3
# downloadXkcd.py - Downloads every single XKCD comic.

import requests, os, bs4

url = 'https://xkcd.com' # starting url
os.makedirs('xkcd', exist_ok=True) # store comics in ./xkcd
while not url.endswith('#'):
# Download the page.
print('Downloading page %s...' % url)
res = requests.get(url)
res.raise_for_status()

soup = bs4.BeautifulSoup(res.text)

# Find the URL of the comic image.
comicElem = soup.select('#comic img')
if comicElem == []:
print('Could not find comic image.')
else:
comicUrl = 'https:' + comicElem[0].get('src')
# Download the image.
print('Downloading iamge %s...' % (comicUrl))
res = requests.get(comicUrl)
res.raise_for_status()

# Save the image to ./xkcd
imageFile = open(os.path.join('xkcd', os.path.basename(comicUrl)), 'wb')
for chunk in res.iter_content(100000):
imageFile.write(chunk)

# Get the Prev button's url.
prevLink = soup.select('a[rel="prev"]')[0]
url = 'http://xkcd.com' + prevLink.get('href')

print('Done')

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档