用Python爬虫爬取炉石原画卡牌图片
前段时间看了点Python的语法以及制作爬虫常用的类库,于是动手制作了一个爬虫尝试爬取一些炉石原画图片。本文仅记录对特定目标网站的分析过程和爬虫代码的编写过程。代码功能很局限,无通用性,仅作为一个一般爬虫程序提供参考。
要爬取的网站入口页面是:https://hearthstone.gamepedia.com/Full_art。网页上半部分的<li>标记了每个炉石资料片图片的名称(其实是锚点连接),通过这些名称就可以获得各个资料片的专题链接,比如,冠军的试炼的专题资料片对应的网址为:https://hearthstone.gamepedia.com/The_Grand_Tournament_full_art
进入专题页面后,可以看到该资料片的图片列表,其中也有各个图片的缩略图连接,但是我想找到每个图片的原图。单个图片介绍的页面连接在每个class="image"的<a>标签中。比如连接:https://hearthstone.gamepedia.com/File:Argent_Horserider_full.png
进入单个图片的介绍页面后,可以找到class='internal'的<a>标签,它的href属性值就是该图片的原图连接。(嗯,判断的依据是从这个连接下载得到的图是最大的。。)
目标网站的情况大致分析完了,好像也不复杂。下面按照分析过程给出一些代码。
题外话:利用Python制作爬虫,我引用了两个类库。分别是BeautifulSoup和requests。Python版本是3.6.1。
首先是根据入口页面获取各个资料片的连接:
def get_links(url):
r = requests.get(url)
r.encoding = "utf-8"
only_li = SoupStrainer(class_=re.compile("toclevel-1"))
lis = BeautifulSoup(r.text, "html.parser", parse_only=only_li)
links = []
for li in lis:
link = li.a["href"]
links.append(link) return links
参数url就是入口连接的字符串值:"https://hearthstone.gamepedia.com/Full_art"。通过requests.get(str)方法获得响应对象并设置其编码格式为"UTF-8"。然后创建了一个SoupStrainer对象,这个对象的作用是在解析(HTML)文档时进行过滤和筛选。class_=re.compile("toclevel-1")表示标签的类中含有值"toclevel-1"。然后就是进行文档解析,解析出来后得到的lis对象,就是包含资料片名称的各个<li>的集合。循环获取其中的<a>标签的href属性值即可。
第二步,根据关键字集合拼接连接。这个很简单。
def get_real_links(basic_url, keywords):
real_links = []
for keyword in keywords:
keyword = keyword[1:]
real_links.append(basic_url+"/"+keyword)
return real_links
basic_url是指:https://hearthstone.gamepedia.com,keywords就是前一步操作得到的links集合。keyword = keyword[1:]是截取去掉锚点"#"号。
第三步就是根据资料片专题画面获取该资料片下的所有图片的图片介绍页面的链接。
def get_img_page_links(basic_url, real_link):
all_img_page_link = []
r = requests.get(real_link)
r.encoding = "utf-8"
ss = SoupStrainer(class_="image")
only_img_a = BeautifulSoup(r.text, "html.parser", parse_only=ss)
for img_a in only_img_a:
all_img_page_link.append(basic_url+img_a["href"])
print(all_img_page_link)
return all_img_page_link
参数real_link是单个资料片的连接。主要代码和第一步是类似的,不再赘述了。
第四步,根据图片介绍页面的链接集合,获取原图片的资源链接。
def get_all_img_link(all_img_page_link):
all_img_link = []
for link in all_img_page_link:
img_name = link[link.index("File:") + len("File:"):]
path = "D://python/heartstoneimg/Knights_of_the_Frozen_Throne_full_art/"+img_name
if os.path.exists(path):
print(img_name+" exists")
continue
else:
print("requesting:%s"%(link))
r = requests.get(link)
r.encoding = "utf-8"
ss = SoupStrainer(class_="internal")
img_a = BeautifulSoup(r.text, "html.parser", parse_only=ss)
print("imag_a:%s" % (img_a))
print(img_a.a["href"])
img_link = img_a.a["href"]
all_img_link.append((img_link, img_name))
time.sleep(10)
if len(all_img_link) > 20:
break
print(all_img_link)
return all_img_link
这里的代码有偷懒的痕迹,在实际下载过程中,如果将所有资料片的所有图片一起循环下载,如果中间有报连接错误(公司网络不行),文档解析的工作就会从头开始。所以我是按照每个资料片,单独下载的。所以,在本地硬盘中创建对应资料片文件夹这项的工作是手动完成的,更换一次资料片的下载也要再手工修改一次代码,这部分可以再完善。这部分程序首先是取得文件名字,然后判断是否已经下载过了,接着获取原图链接,并把图片名称和原图链接做成一个tuple存储在集合中。这里我每次运行只解析二十张图片的信息(还是网络原因)。
最后一步就是图片下载了。
def do_get_img(all_image_link): for img_link in all_image_link:
path = "D://python/heartstoneimg/Knights_of_the_Frozen_Throne_full_art/"+img_link[1];
if os.path.exists(path):
print(img_link[1]+" exists.")
continue
else:
print("downloading:%s" % (img_link[0]))
try:
pic = requests.get(img_link[0], timeout=60)
except requests.exceptions.ConnectionError:
print("fail or timeout!!")
continue
# path = "D://python/heartstoneimg/basic_full_art/"+img_link[1]
print("writing:%s" % (path))
file = open(path, 'wb')
file.write(pic.content)
file.close()
time.sleep(10)
好像也很简单,每张图片下载的超时时间是六十秒,每次下载完一张图片后延迟十秒再下载,不然有时网站会因为你访问太过频繁而拒绝访问。
main部分的代码。
from bs4 import BeautifulSoup
import requests
import re
from bs4 import SoupStrainer
import time
import os
import socket
def start_get_img():
url = "http://hearthstone.gamepedia.com/Full_art"
keywords = get_links(url)
basic_url = "http://hearthstone.gamepedia.com"
real_links = get_real_links(basic_url, keywords)
all_img_page_link = get_img_page_links(basic_url, real_links[11])
all_img_link = get_all_img_link(all_img_page_link)
do_get_img(all_img_link) if __name__ == "__main__":
start_get_img()
get_img_page_links(str,str)方法的第二个参数是当前的资料片链接。更完善的做法是循环real_links集合进行下载。
如果网络正常,每个资料片一百多张图片可以在一个小时内下载完。
我把下载到的原画图片作为资源制作了一个网站。
http://www.blz-art.com
有兴趣的可以去看下。
用Python爬虫爬取炉石原画卡牌图片的更多相关文章
- Python爬虫 - 爬取百度html代码前200行
Python爬虫 - 爬取百度html代码前200行 - 改进版, 增加了对字符串的.strip()处理 源代码如下: # 改进版, 增加了 .strip()方法的使用 # coding=utf-8 ...
- 用Python爬虫爬取广州大学教务系统的成绩(内网访问)
用Python爬虫爬取广州大学教务系统的成绩(内网访问) 在进行爬取前,首先要了解: 1.什么是CSS选择器? 每一条css样式定义由两部分组成,形式如下: [code] 选择器{样式} [/code ...
- 使用Python爬虫爬取网络美女图片
代码地址如下:http://www.demodashi.com/demo/13500.html 准备工作 安装python3.6 略 安装requests库(用于请求静态页面) pip install ...
- Python爬虫|爬取喜马拉雅音频
"GOOD Python爬虫|爬取喜马拉雅音频 喜马拉雅是知名的专业的音频分享平台,用户规模突破4.8亿,汇集了有声小说,有声读物,儿童睡前故事,相声小品等数亿条音频,成为国内发展最快.规模 ...
- python爬虫爬取内容中,-xa0,-u3000的含义
python爬虫爬取内容中,-xa0,-u3000的含义 - CSDN博客 https://blog.csdn.net/aiwuzhi12/article/details/54866310
- Python爬虫爬取全书网小说,程序源码+程序详细分析
Python爬虫爬取全书网小说教程 第一步:打开谷歌浏览器,搜索全书网,然后再点击你想下载的小说,进入图一页面后点击F12选择Network,如果没有内容按F5刷新一下 点击Network之后出现如下 ...
- python爬虫—爬取英文名以及正则表达式的介绍
python爬虫—爬取英文名以及正则表达式的介绍 爬取英文名: 一. 爬虫模块详细设计 (1)整体思路 对于本次爬取英文名数据的爬虫实现,我的思路是先将A-Z所有英文名的连接爬取出来,保存在一个cs ...
- 一个简单的python爬虫,爬取知乎
一个简单的python爬虫,爬取知乎 主要实现 爬取一个收藏夹 里 所有问题答案下的 图片 文字信息暂未收录,可自行实现,比图片更简单 具体代码里有详细注释,请自行阅读 项目源码: # -*- cod ...
- python爬虫-爬取百度图片
python爬虫-爬取百度图片(转) #!/usr/bin/python# coding=utf-8# 作者 :Y0010026# 创建时间 :2018/12/16 16:16# 文件 :spider ...
随机推荐
- 本地启动activemq,报错解决
本地启动activemq时,报错.可以看到是5672端口被占用.在网上查了各种资料,有说是杀掉进程的,有说是禁用Internet Connection Sharing (ICS)服务的,楼主试了都没生 ...
- 使用 ahk 让普通键盘变为Dvorak键盘
本文告诉大家,如何使用软件做出Dvorak键盘. 在开始说如何做之前,需要告诉大家,什么是Dvorak键盘. Dvorak Simplified Keyboard /ˈdvɔːræk, dəˈvɔː- ...
- MySQL 学习 --- 数据结构和索引
本文参考了多篇文章集成的笔记,希望各位学习之前可以阅读以下参考资料先 概述 文章分几个部分 :第一部分介绍了B-Tree 和 B+Tree 这种数据结构作为索引:第二部分介绍索引的最左前缀原则和覆盖索 ...
- git 查看和撤销
linux下文本的新建和追加内容 git cat-file -p ID可查看当前master的数据 观察Git 內部如何储存Commit 随便便抓一個 Commit 的 SHA1 开始: git ca ...
- Java代理(二)
前面说到了java的静态代理,这次来看看动态代理. 假设有如下接口和实现方法: package proxy; public interface Subject { public void reques ...
- Java Singleton(单例模式) 实现详解
什么是单例模式? Intend:Ensure a class only has one instance, and provide a global point of access to it. 目标 ...
- 使用外部属性文件配置Bean以及Bean的生命周期方法
1.使用外部属性文件配置Bean 在配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean ...
- MySQL中的存储过程和函数
存储过程和函数 简单的说,存储过程就是一条或者多条SQL语句的集合.可以视为批文件,但是其作用不仅仅局限于批处理.本文主要介绍如何创建存储过程和存储函数,以及如何调用.查看.修改.删除存储过程和存储函 ...
- 软件架构系列一:C4模型
本文要点预览:因为软件系统的分布式特点以及开发团队的分布性,了解软件架构的基础变得越来越重要.而在过度设计和毫无设计之间,我们应该把注意力放在对软件系统有重大影响的决策和权衡上.好的架构师应该是团队的 ...
- time模块,计算时间差
计算当前时间与所输入的时间的时间差 #1 计算当前时间的时间戳时间 t_now = time.time() # 计算以前的时间的时间戳时间 t_before = input('请输入时间(例如:200 ...