坦克世界WOT知识图谱三部曲之爬虫篇

2024-03-08 09:40

本文主要是介绍坦克世界WOT知识图谱三部曲之爬虫篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 关于坦克世界
  • 1. 爬虫任务
  • 2. 获取坦克列表
  • 3. 获取坦克具体信息
  • 结束语

关于坦克世界

  《坦克世界》(World of Tanks, WOT)是我在本科期间玩过的一款战争网游,由Wargaming公司研发。2010年10月30日在俄罗斯首发,2011年4月12日在北美和欧洲推出,2011年3月15日在中国由空中网代理推出(2020年,国服由360代理)。游戏背景设定在二战时期,玩家会扮演1930到1960年代的战车进行对战,要求战略和合作性,游戏中的战车根据历史高度还原。

  坦克世界官网:https://wotgame.cn/
  坦克世界坦克百科:https://wotgame.cn/zh-cn/tankopedia/#wot&w_m=tanks

在这里插入图片描述

1. 爬虫任务

在这里插入图片描述
  当前的WOT有五种坦克类型,11个系别。我们要构建一个关于坦克百科的知识图谱,接下来就要通过爬虫来获取所有坦克的详细信息,比如坦克的等级、火力、机动性、防护能力、侦察能力等等。以当前的八级霸主中国重型坦克BZ-176为例,坦克的详细信息如下:

在这里插入图片描述
在这里插入图片描述

2. 获取坦克列表

在这里插入图片描述
  常规操作,F12+F5查看一下页面信息,定位到坦克列表的具体请求:

在这里插入图片描述
  是一个POST请求,返回的是一个JSON格式的数据,包含了该类型坦克的一些基本信息:

在这里插入图片描述
  POST请求参数如下:

在这里插入图片描述

  特别说明一下:构建该请求header时,Content-Length参数是必须的。

  代码实现:

# -*- coding: utf-8 -*-
# Author  : xiayouran
# Email   : youran.xia@foxmail.com
# Datetime: 2023/9/29 22:43
# Filename: spider_wot.py
import os
import time
import json
import requestsclass WOTSpider:def __init__(self):self.base_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/117.0.0.0 Safari/537.36','Accept-Encoding': 'gzip, deflate, br','Accept-Language': 'zh-CN,zh;q=0.9',}self.post_headers = {'Accept': 'application/json, text/javascript, */*; q=0.01','Content-Length': '135','Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}self.from_data = {'filter[nation]': '','filter[type]': 'lightTank','filter[role]': '','filter[tier]': '','filter[language]': 'zh-cn','filter[premium]': '0,1'}self.tank_list_url = 'https://wotgame.cn/wotpbe/tankopedia/api/vehicles/by_filters/'self.tank_label = ['lightTank', 'mediumTank', 'heavyTank', 'AT-SPG', 'SPG']self.tanks = {}def parser_tanklist_html(self, html_text):json_data = json.loads(html_text)for data in json_data['data']['data']:self.tanks[data[0] + '_' + data[4]] = {'tank_nation': data[0],'tank_type': data[1],'tank_rank': data[3],'tank_name': data[4],'tank_name_s': data[5],'tank_url': data[6],'tank_id': data[7]}def run(self):for label in self.tank_label:self.from_data['filter[type]'] = labelhtml_text = self.get_html(self.tank_list_url, method='POST', from_data=self.from_data)if not html_text:print('[{}] error'.format(label))continueself.parser_tanklist_html(html_text)time.sleep(3)self.save_json(os.path.join(self.data_path, 'tank_list.json'), self.tanks)if __name__ == '__main__':tank_spider = WOTSpider()tank_spider.run()

  上述代码只实现了一些重要的函数及变量声明,完整的代码可以从github上拉取:WOT

3. 获取坦克具体信息

  坦克具体信息的页面就是一个纯HTML页面了,一个GET请求就可以获得。当然啦,具体怎么分析的就不细说了,对爬虫技术感兴趣的同学们可以找找资料,这里就只说一下抓取流程。
  先分析GET请求:https://wotgame.cn/zh-cn/tankopedia/60209-Ch47_BZ_176/,可以分成三部分:
  Part 1:基本的url请求:https://wotgame.cn/zh-cn/tankopedia
  Part 2:坦克的idBZ-176坦克的id60209,每个坦克都是唯一的,这个参数通过上一个步骤的POST请求可以获取到;
  Part 3:坦克的名称:Ch47_BZ_176,这个参数也可以通过上一个步骤的POST请求可以获取到。
  这样就可以为每个坦克构造一个对应的url了,只需解析该url对应的界面即可。解析的时候我分成了两部分,先对坦克的基本信息进行解析,比如坦克系别、等级及价格等等,由BeautifulSoup库实现,坦克的具体信息,比如火力、机动、防护及侦察能力,这些信息是由JavaScript代码动态请求得到的,这里为了简便没有分析具体的js代码,而是先使用selenium库进行网页渲染,然后再使用BeautifulSoup库进行解析。这里不再细说,下面给出页面解析的代码:

# -*- coding: utf-8 -*-
# Author  : xiayouran
# Email   : youran.xia@foxmail.com
# Datetime: 2023/9/29 22:43
# Filename: spider_wot.py
import requests
from tqdm import tqdm
from bs4 import BeautifulSoup, Tag
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWaitclass WOTSpider:def __init__(self):passdef is_span_with_value(self, driver):try:element = driver.find_element(By.XPATH, "//span[@data-bind=\"text: ttc().getFormattedBestParam('maxHealth', 'gt')\"]")data = element.text.strip()if data:return Trueexcept:return Falsedef get_html_driver(self, url):self.driver.get(url)self.wait.until(self.is_span_with_value)page_source = self.driver.page_sourcereturn page_sourcedef parser_tankinfo_html(self, html_text):tank_info = copy.deepcopy(self.tank_info)soup = BeautifulSoup(html_text, 'lxml')# tank_name = soup.find(name='h1', attrs={'class': 'garage_title garage_title__inline js-tank-title'}).strip()tank_statistic = soup.find_all(name='div', attrs={'class': 'tank-statistic_item'})for ts in tank_statistic:ts_text = [t for t in ts.get_text().split('\n') if t]if len(ts_text) == 5:tank_info['价格'] = {'银币': ts_text[-3],'经验': ts_text[-1]}else:tank_info[ts_text[0]] = ts_text[-1]tank_property1 = soup.find(name='p', attrs='garage_objection')tank_property2 = soup.find(name='p', attrs='garage_objection garage_objection__collector')if tank_property1:tank_info['性质'] = tank_property1.textelif tank_property2:tank_info['性质'] = tank_property2.textelse:tank_info['性质'] = '银币坦克'tank_desc_tag = soup.find(name='p', attrs='tank-description_notification')if tank_desc_tag:tank_info['历史背景'] = tank_desc_tag.texttank_parameter = soup.find_all(name='div', attrs={'class': 'specification_block'})for tp_tag in tank_parameter:param_text = tp_tag.find_next(name='h2', attrs={'class': 'specification_title specification_title__sub'}).get_text()# spec_param = tp_tag.find_all_next(name='div', attrs={'class': 'specification_item'})spec_param = [tag for tag in tp_tag.contents if isinstance(tag, Tag) and tag.attrs['class'] == ['specification_item']]spec_info = {}for tp in spec_param:tp_text = [t for t in tp.get_text().replace(' ', '').split('\n') if t]if not tp_text or not tp_text[0][0].isdigit():continuespec_info[tp_text[-1]] = ' '.join(tp_text[:-1])tank_info[param_text] = spec_inforeturn tank_infodef run(self):file_list = [os.path.basename(file)[:-5] for file in glob.glob(os.path.join(self.data_path, '*.json'))]for k, item in tqdm(self.tanks.items(), desc='Crawling'):file_name = k.replace('"', '').replace('“', '').replace('”', '').replace('/', '-').replace('\\', '').replace('*', '+')if file_name in file_list:continuetank_url = self.tank_url + str(item['tank_id']) + '-' + item['tank_url']html_text = self.get_html_driver(tank_url)# html_text = self.get_html(tank_url, method='GET')tank_info = self.parser_tankinfo_html(html_text)self.tanks[k].update(tank_info)self.save_json(os.path.join(self.data_path, '{}.json'.format(file_name)), self.tanks[k])time.sleep(1.5)self.save_json(os.path.join(self.data_path, 'tank_list_detail.json'), self.tanks)if __name__ == '__main__':tank_spider = WOTSpider()tank_spider.run()

  大约半个小时即可获取全部的坦克信息,如下:

在这里插入图片描述

  Selenium 库依赖chromedriver,需要根据自己的Chrome浏览器版本下载合适的版本,chromedriver的官方下载地址为:https://chromedriver.chromium.org/downloads/version-selection

结束语

  本篇的完整代码及爬取的结果已经同步到仓库中,感兴趣的话可以拉取一下,下一篇文章就基于当前获取到的坦克信息来构造一个关于坦克百科的知识图谱。

开源代码仓库


  如果喜欢的话记得给我的GitHub仓库WOT点个Star哦!ヾ(≧∇≦*)ヾ


  公众号已开通:夏小悠,关注以获取更多关于Python文章、AI领域最新技术、LLM大模型相关论文及内部PPT等资料^_^

这篇关于坦克世界WOT知识图谱三部曲之爬虫篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/786715

相关文章

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

亮相WOT全球技术创新大会,揭秘火山引擎边缘容器技术在泛CDN场景的应用与实践

2024年6月21日-22日,51CTO“WOT全球技术创新大会2024”在北京举办。火山引擎边缘计算架构师李志明受邀参与,以“边缘容器技术在泛CDN场景的应用和实践”为主题,与多位行业资深专家,共同探讨泛CDN行业技术架构以及云原生与边缘计算的发展和展望。 火山引擎边缘计算架构师李志明表示:为更好地解决传统泛CDN类业务运行中的问题,火山引擎边缘容器团队参考行业做法,结合实践经验,打造火山

Python爬虫-贝壳新房

前言 本文是该专栏的第32篇,后面会持续分享python爬虫干货知识,记得关注。 本文以某房网为例,如下图所示,采集对应城市的新房房源数据。具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。接下来,跟着笔者直接往下看正文详细内容。(附带完整代码) 正文 地址:aHR0cHM6Ly93aC5mYW5nLmtlLmNvbS9sb3VwYW4v 目标:采集对应城市的

【网络安全的神秘世界】搭建dvwa靶场

🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 下载DVWA https://github.com/digininja/DVWA/blob/master/README.zh.md 安装DVWA 安装phpstudy https://editor.csdn.net/md/?articleId=1399043

C语言入门系列:探秘二级指针与多级指针的奇妙世界

文章目录 一,指针的回忆杀1,指针的概念2,指针的声明和赋值3,指针的使用3.1 直接给指针变量赋值3.2 通过*运算符读写指针指向的内存3.2.1 读3.2.2 写 二,二级指针详解1,定义2,示例说明3,二级指针与一级指针、普通变量的关系3.1,与一级指针的关系3.2,与普通变量的关系,示例说明 4,二级指针的常见用途5,二级指针扩展到多级指针 小结 C语言的学习之旅中,二级

每日一练:攻防世界:5-1 MulTzor

一、XorTool 基于 XOR(异或)运算实现。它可以帮助您快速地对文本、二进制文件进行加密解密操作。 认识XorTool工具: 让我们先去认识一下工具: xortool.py 是基于 python 的脚本,用于完成一些 xor 分析,包括: 猜想 key 的长度 猜想 key 的值 解密一些经过 xoe 加密的文件 也就是说当遇到不知道文件类型的文件,可以尝试去看看它是否被xo

爬虫阶段思考

内容:写这篇文章是因为最近帮同学改了很多的爬虫代码,感触良多。 我用豆瓣为例,并不是不会用别的,而是这个我个人感觉最经典。然后还会写我遇到的一些问题以及解决方法。 首先,我们得先知道怎样爬取。我用的scrapy框架爬取。 我对此图的理解就是: 从spiders中获得一个请求(REQUEST),通过引擎传递给调度器,之后再返回给引擎,引擎把url封装好后传递给下载器,下载器将资源下载好后

关于CPU的一点知识

首先说一下,CPU是干啥的: CPU所负责的就是解释和运行最终转换成机器语言的程序内容 我们需要知道的CPU结构:重点需要关注寄存器 运算器 简单说就是负责运算从内存读取到寄存器中的数据,可以看作一个数据加工厂,就是对寄存器中的数据做运算,这些运算包含基本的算术和逻辑运算。 算术逻辑单元(ALU) 这个是运算器中重要的一个组成,主要负责的就是对数据的处理,从而实现对数据的算术和

计算机组成入门知识

前言👀~ 数据库的知识点先暂且分享到这,接下来开始接触计算机组成以及计算机网络相关的知识点,这一章先介绍一些基础的计算机组成知识 一台计算机如何组成的? 存储器 CPU cpu的工作流程 主频 如何衡量CPU好坏呢? 指令 操作系统 操作系统功能 操作系统"内核"  如果各位对文章的内容感兴趣的话,请点点小赞,关注一手不迷路,如果内容有什么问题的话,欢迎各位

【Flink metric】Flink指标系统的系统性知识:以便我们实现特性化数据的指标监控与分析

文章目录 一. Registering metrics:向flink注册新自己的metrics1. 注册metrics2. Metric types:指标类型2.1. Counter2.2. Gauge2.3. Histogram(ing)4. Meter 二. Scope:指标作用域1. User Scope2. System Scope ing3. User Variables 三.