坦克世界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等资料^_^

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149516.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

IDT 一款自动化挖掘未授权访问漏洞的信息收集工具

IDT v1.0 IDT 意为 Interface detection(接口探测) 项目地址: https://github.com/cikeroot/IDT/该工具主要的功能是对批量url或者接口进行存活探测,支持浏览器自动打开指定的url,避免手动重复打开网址。只需输入存在批量的url文件即可。 …

Linux删除空目录/非空目录和文件

一、删除目录 删除名为mydir的空目录: rmdir mydir 删除名为mydir的非空目录(非空目录是指该目录包含了其他文件或子目录,而不是空的或没有任何内容的目录) rm -r mydir 删除mydir1下的空目录mydir2 rmdir mydir1/mydir2 删除当前目录下所有以dir一个数字结尾的目录…

Nginx限流熔断

一、Nginx限流熔断 Nginx 是一款流行的反向代理和负载均衡服务器,也可以用于实现服务熔断和限流。通过使用 Nginx 的限流和熔断模块,比如:ngx_http_limit_req_module 和 ngx_http_limit_conn_module,可以在代理层面对服务进行限流…

set和map的封装

目录 介绍 红黑树代码 set insert的迭代器转换问题 为什么会有这样的问题? 如何解决 代码 map 注意点 代码 介绍 set和map的底层都是红黑树,所以我们可以在自己实现的红黑树(简易版)的基础上,进行封装,成为简易的set和map 红黑树代码 #pragma once#include <…

GEE16: 区域日均降水量计算

Precipitation 1. 区域日均降水量计算2. 降水时间序列3. 降水数据年度时间序列对比分析 1. 区域日均降水量计算 今天分析一个计算区域日均降水量的方法&#xff1a; 数据信息&#xff1a;   Climate Hazards Group InfraRed Precipitation with Station data (CHIRPS) is a…

嵌入式软件架构基础设施设计方法

大家好&#xff0c;今天分享一篇嵌入式软件架构设计相关的文章。 软件架构这东西&#xff0c;众说纷纭&#xff0c;各有观点。在我看来&#xff0c;软件架构是软件系统的基本结构&#xff0c;包含其组件、组件之间的关系、组件设计与演进的规则&#xff0c;以及体现这些规则的基…

图像处理与计算机视觉--第五章-图像分割-Canny算子

文章目录 1.边缘检测算子分类2.Canny算子核心理论2.1.Canny算子简单介绍2.2.Canny算子边缘检测指标2.3.Canny算子基本原理 3.Canny算子处理流程3.1.高斯滤波去噪声化3.2.图像梯度搜寻3.3.非极大值抑制处理3.4.双阈值边界处理3.5.边界滞后技术跟踪3.6.Canny算子边缘检测的特点 4…

MySQL 索引的作用、索引结构及执行流程介绍(索引篇 一)

索引介绍 MySQL索引&#xff08;index&#xff09;是一种用于加快数据库中数据搜索和查询的数据结构。它类似于书籍的目录&#xff0c;可以帮助数据库快速定位和访问特定数据&#xff0c;而无需扫描整个数据表。 索引的作用和缺点 1. 加快数据搜索&#xff1a;通过使用索引&…

Linux——指令初识

Linux下基本指令 前言一、 ls 指令二、 pwd命令三、cd 指令四、 touch指令五、mkdir指令六、rmdir指令 && rm 指令七、man指令八、cp指令九、mv指令十、cat指令十一、.more指令十二、less指令十三、head指令十四、tail指令总结 前言 linux的学习开始啦&#xff01; 今…

我的创作纪念日-第1024天

文章目录 一、机缘二、收获三、日常四、憧憬 一、机缘 不知不觉&#xff0c;已经加入CSDN这个大家庭5年多了&#xff0c;回想起3年前发布第一篇博客的时候&#xff0c;那时我记得很清楚&#xff0c;我在做项目时遇到报错&#xff0c;解决问题之后&#xff0c;然后想起了好多人…

SpringCloud(二)Docker、Spring AMQP、ElasticSearch

文章目录 DockerDocker与虚拟机Docker架构镜像、容器、镜像托管平台Docker架构Docker实践 Spring AMQP简单使用案例工作队列- WorkQueue发布订阅服务FanoutExchangeDirectExchangeTopicExchange 消息转换器 ElasticSearch倒排索引IK分词器IK分词拓展与停用字典 操作索引库mappi…

c#基础逻辑练习案例

第二章综合练习小游戏 练习内容 向控制台输出“这是学号姓名的C#基础小游戏”。向控制台换行再输出“请输入你的游戏昵称&#xff1a;”。向控制台输入你的游戏昵称&#xff0c;赋给一个字符串变量。向控制台换行再输出“请输入你的性别&#xff1a;”。向控制台输入你的性别…

创建vue3工程

一、新建工程目录E:\vue\projectCode\npm-demo用Visual Studio Code 打开目录 二、点击新建文件夹按钮&#xff0c;新建vue3-01-core文件夹 三、右键vue3-01-core文件夹点击在集成终端中打开 四、初始化项目&#xff0c;输入npm init 一直敲回车直到创建成功如下图 npm init 五…

Spring5应用之Cglib动态代理

作者简介&#xff1a;☕️大家好&#xff0c;我是Aomsir&#xff0c;一个爱折腾的开发者&#xff01; 个人主页&#xff1a;Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客 当前专栏&#xff1a;Spring5应用专栏_Aomsir的博客-CSDN博客 文章目录 前言Cglib动态代理…

uCOSIII实时操作系统 二 同步与通信

目录 同步概念&#xff1a; 互斥概念&#xff1a; 临界区概念&#xff1a; 任务时间概念&#xff1a; 信号量概念&#xff1a; 互斥信号量概念&#xff1a; 事件标志组概念&#xff1a; 消息邮箱和消息梯队概念&#xff1a; 内存管理概念&#xff1a; 如何从裸机开发…

矢量图形编辑软件illustrator 2023 mac特点介绍

illustrator 2023 mac是一款矢量图形编辑软件&#xff0c;用于创建和编辑排版、图标、标志、插图和其他类型的矢量图形。 illustrator mac软件特点 矢量图形&#xff1a;illustrator创建的图形是矢量图形&#xff0c;可以无限放大而不失真&#xff0c;这与像素图形编辑软件&am…

六、vpp 流表+负载均衡

草稿&#xff01;&#xff01;&#xff01; vpp node其实就是三个部分 1、plugin init 2、set command 3、function 实现功能&#xff0c;比如这里的流表 今天我们再用VPP实现一个流表的功能 一、流表 1.1流表----plugin init VLIB_REGISTER_NODE 注册流表节点 // 注册流…

纯css实现3D鼠标跟随倾斜

老规矩先上图 为什么今天会想起来整这个呢?这是因为和我朋友吵架, 就是关于这个效果的,就是这个 卡片懸停毛玻璃效果, 我朋友认为纯css也能写, 我则坦言他就是在放狗屁,这种跟随鼠标的3D效果要怎么可能能用纯css写, 然后吵着吵着发现,欸,好像真能用css写哦,我以前还写过这种…

去雨去雪去雾数据集构建

在进行去雨去雪去雾算法的学习过程中&#xff0c;需要构建去雨去雪去雾数据集&#xff0c;本文参考Learning Multiple Adverse Weather Removal via Two-stage Knowledge Learning and Multi-contrastive Regularization: Toward a Unified Model论文中的数据集设定&#xff0c…

面试题 17.24. 最大子矩阵

链接&#xff1a; 面试题 17.24. 最大子矩阵 题解&#xff1a; 这样我们就将二维问题转化为了一维问题&#xff0c;现在另一个问题就是怎么把所有情况都遍历到呢&#xff1f; 我们以第i行为第一行&#xff0c;向下延申&#xff0c;设最后一行为第j行&#xff0c;我们就i在这么…