Texture Haven Spider
目录
- 安装scrapy
- 创建scrapy项目
- 设置item
- 开始爬取
- 构建数据库
- 下载图片
- 运行
- 项目地址
- 总结
前面写了一个博客来介绍一个插件:TextureHavenForBlender,博客可以参见这里。通过该插件,用户可以直接在Blender中查看并下载TextureHaven的所有纹理贴图,随后通过下载的纹理贴图构建材质。所有这些过程仅仅需要点击几个按钮。
该插件中,在Blender中查看TextureHaven的所有纹理贴图的步骤需要联网在TextureHaven的网站上下载图片。由于TextureHaven网站对爬虫有较高的管制,实现起来并不容易。这里采用scrapy框架先爬取TextureHaven上所有纹理的缩略图以及所有的下载链接,并为此构建一个数据库,最后使用Blender的python读取该数据库即可。
安装scrapy
安装Scrapy比较简单,直接使用pip进行安装即可。由于我们还需要使用scrapy下载图片,所以还需要安装pillow库:
pip install scrapy pillow
创建scrapy项目
使用命令创建项目TextureHavenSpider:
scrapy startproject THSpider
设置item
首先,我们需要设置item来保存需要爬取的数据(对应的数据的含义见代码),修改items.py
文件为:
import scrapyclass TexturehavenspiderItem(scrapy.Item):main_path = scrapy.Field()categ_url = scrapy.Field() # 纹理所属类别的网址categ_img = scrapy.Field() # 纹理所属类别的缩略图网址categ_tag = scrapy.Field() # 纹理所属类别的标签categ_path = scrapy.Field() # 纹理所属列别的缩略图的本地地址textu_url = scrapy.Field() # 纹理的网址textu_img = scrapy.Field() # 纹理的缩略图网址textu_tag = scrapy.Field() # 纹理标签textu_path = scrapy.Field() # 纹理缩略图的本地地址textu_1k_url = scrapy.Field() # 1k纹理的网址textu_2k_url = scrapy.Field() # 2k纹理的网址textu_4k_url = scrapy.Field() # 4k纹理的网址textu_8k_url = scrapy.Field() # 8k为你的网址
开始爬取
首先在THSpider类中添加如下属性:
class THSpider(scrapy.spiders.Spider):name = "TextureHaven"allowed_domains = ["texturehaven.com"]start_urls = ["https://texturehaven.com/textures"]main_url = "https://texturehaven.com/"main_path = "./Thumbails/"
此处main_url是在爬取过程中,网页需要跳转的基础的url,main_path是图像保存的位置。
随后修改parse函数为:
def parse(self, response):for sel in response.xpath("//div[@class='category-list-images']/ul/a"):img_url_text = sel.xpath("li/div/@style").extract()[0]categ_url = self.main_url + sel.xpath("@href").extract()[0]categ_img = self.main_url + re.search("\/files\/tex\_images\/thumbnails/([\w]*)\.jpg", img_url_text).group()categ_tag = sel.xpath("li/p/text()").extract()[0]yield scrapy.Request(categ_url, callback=self.categ_parse, meta={"categ_url":categ_url, "categ_img": categ_img, "categ_tag": categ_tag})
该函数将尝试爬取 start_urls
中网址的源码,并反馈回response。使用xpath来解析源码,关于xpath的用法,请自行去网上查询。这次爬取需要找到所有纹理的分类信息,其位于<div class="category-list-images">
标签中,所以可以使用response.xpath("//div[@class='category-list-images']/ul/a"
来找到class
为category-list-images
的div下的<ul>
下的所有<a>
标签。随后使用li/div/@style
查找style下的文本,其中保存了缩略图的地址信息,使用正则表达式来\/files\/tex\_images\/thumbnails/([\w]*)\.jpg
查询列别的缩略图的下载地址。缩略图的跳转网址通过href属性查询@href
,列别的标签通过li/p/text()
查询。
最后一行发起一个新的请求用来请求类别的跳转网址,并将上述查询到的信息发送到下一层请求中。
随后,我们编写跳转请求后的解析函数:
def categ_parse(self, response):for sel in response.xpath("//div[@id='item-grid']/a"):textu_url = self.main_url + sel.xpath("@href").extract()[0]textu_img = self.main_url +sel.xpath("div/div/img[@class='thumbnail']/@data-src").extract()[0]textu_tag = sel.xpath("div/div[@class='description-wrapper']/div/div/h3/text()").extract()[0]yield scrapy.Request(textu_url, callback=self.texture_parse,meta = {"categ_url":response.meta["categ_url"], "categ_img": response.meta["categ_img"], "categ_tag": response.meta["categ_tag"],"textu_url": textu_url, "textu_img": textu_img, "textu_tag": textu_tag})
该请求将爬取所有类别内的所有纹理的缩略图和缩略图的标签以及下载地址,并往下进一步请求每个纹理内部的信息。
在请求后的网址中,我们需要的信息位于:
所以,首先通过//div[@id='item-grid']/a
来获取id
为item-grid
的div
下的所有<a>
标签。并分别找到纹理的缩略图、缩略图下载地址以及纹理的标签。最后一行是进一步跳转到每个纹理的内部信息中,获取所有纹理资源的下载地址。
因此,需要创建函数来解析下一步的网址:
def texture_parse(self, response):th_item = TexturehavenspiderItem()textu_1k = ""textu_2k = ""textu_4k = ""textu_8k = ""urls = []for sel in response.xpath("//div[@class='map-type'][1]/div[3]/div"):urls.append(sel.xpath("a[1]/@href").extract()[0])for u in urls:if "1k" in u:textu_1k = self.main_url + uif "2k" in u:textu_2k = self.main_url + uif "4k" in u:textu_4k = self.main_url + uif "8k" in u:textu_8k = self.main_url + uth_item["main_path"] = self.main_pathth_item["categ_url"] = response.meta["categ_url"]th_item["categ_img"]= response.meta["categ_img"]th_item["categ_tag"] = response.meta["categ_tag"]th_item["categ_path"] = self.main_path + "categories_thumbails/" + response.meta["categ_tag"] + ".jpg"th_item["textu_url"] = response.meta["textu_url"]th_item["textu_img"] = response.meta["textu_img"]th_item["textu_tag"] = response.meta["textu_tag"]th_item["textu_path"] = self.main_path + response.meta["categ_tag"] + "/" + response.meta["textu_tag"] + ".jpg"th_item["textu_1k_url"] = textu_1kth_item["textu_2k_url"] = textu_2kth_item["textu_4k_url"] = textu_4kth_item["textu_8k_url"] = textu_8kyield th_item
本次相应的目标信息位于:
每个纹理分为很多种类型,同时有四种分辨率可供下载。这里,我们选择下载所有的纹理的zip文件。同样地,使用xpath方式进行解析,找到1k、2k、4k和8k分别对应的下载地址。
最后将所有信息组成的item yield出来。
构建数据库
python3中自带有SQLite数据库,为了不下载第三方数据库,所以这里就使用SQLite数据库。具体的使用方法请自行查找学习。
构建数据库需要使用到pipeline,修改pipelines.py文件,添加如下的类:
class SQLitePipeline(object):
首先编写open_spider函数,该函数将在爬虫开始运行时执行,这里用于初始化数据库:
def open_spider(self, spider):self.conn = sqlite3.connect("./Thumbails/TextureHavenDataSet.db")sql_cmd = "CREATE TABLE IF NOT EXISTS TEXTUREHAVEN \( \textu_tag TEXT PRIMARY KEY, \categ_tag TEXT, \textu_img TEXT, \categ_img TEXT, \textu_path TEXT, \categ_path TEXT, \textu_1k_url TEXT, \textu_2k_url TEXT, \textu_4k_url TEXT, \textu_8k_url TEXT \)"self.conn.execute(sql_cmd)self.conn.commit()self.cur = self.conn.cursor()
随后编写process_item函数,该函数用于处理item,并将数据写入数据库:
def process_item(self, item, spider):sql_cmd = "INSERT INTO TEXTUREHAVEN \(textu_tag, categ_tag, textu_img, categ_img, \textu_path, categ_path, textu_1k_url, textu_2k_url, \textu_4k_url, textu_8k_url) \VALUES \( \:textu_tag, :categ_tag, :textu_img, :categ_img, \:textu_path, :categ_path, :textu_1k_url, :textu_2k_url, \:textu_4k_url, :textu_8k_url \)"self.cur.execute(sql_cmd, {"textu_tag": item["textu_tag"],"categ_tag": item["categ_tag"],"textu_img": item["textu_img"],"categ_img": item["categ_img"],"textu_path": item["textu_path"],"categ_path": item["categ_path"],"textu_1k_url": item["textu_1k_url"],"textu_2k_url": item["textu_2k_url"],"textu_4k_url": item["textu_4k_url"],"textu_8k_url": item["textu_8k_url"],})self.conn.commit()
最后编写close_spider函数,在关闭spider时会被执行,主要用于释放数据库句柄:
def close_spider(self, spider):self.conn.close()
同时,修改TexturehavenspiderPipeline类,用于在item产生后生成相应的文件夹:
class TexturehavenspiderPipeline:def process_item(self, item, spider):if not os.path.exists(item["main_path"]):os.mkdir(item["main_path"])if not os.path.exists(item["main_path"] + "categories_thumbails/"):os.mkdir(item["main_path"] + "categories_thumbails/")if not os.path.exists(item["main_path"] + item["categ_tag"]):os.mkdir(item["main_path"] + item["categ_tag"])return item
为了让该pipeline生效,需要在setting.py文件的ITEM_PIPELINES中添加'TextureHavenSpider.pipelines.SQLitePipeline': 1
下载图片
与前面的生成数据库相同,这里也采用pipeline来下载图片。在pipelines.py文件中添加:
class MyImagesPipeline(ImagesPipeline):def get_media_requests(self, item, info):categ_img_url = item["categ_img"]yield scrapy.Request(categ_img_url, meta={"path": item["categ_path"]})textu_img_url = item["textu_img"]yield scrapy.Request(textu_img_url, meta={"path": item["textu_path"]})def item_completed(self, results, item, info):if not results[0][0]:with open('img_error.txt', 'a')as f:error = str(item['categ_path']+' '+item['categ_img'])f.write(error)f.write('\n')raise DropItem("Failed to download!")return itemdef file_path(self, request, response=None, info=None):name = request.meta['path']return name
其中get_media_requests函数用于请求图片下载地址,通过item中的缩略图地址,发送相关请求即可。item_completed函数在上述请求完成后执行,主要用于处理一些请求失败的处理,这里将其请求失败的地址写入到img_error文件中。最后的file_path是图片的保存地址。
为了让该pipeline生效,需要在setting.py文件中添加:
ITEM_PIPELINES = {'TextureHavenSpider.pipelines.MyImagesPipeline': 1,'TextureHavenSpider.pipelines.SQLitePipeline': 1}
IMAGES_STORE = './'
运行
在所有上述内容完成后,在终端输入:
scrapy crawl TextureHaven
项目地址
- https://gitee.com/Huakim/TextureHavenSpider
- https://github.com/HakimHua/TextureHavenSpider
总结
使用scrapy进行爬虫处理非常方便,其可以非常简单地完成大量内容的爬取工作,还可以在一定程度上避免许多网站设置的反爬限制。当然,随着现在的反爬技术升级,有许多网站还是很难爬取的。
参考:scrapy官方文档
Texture Haven Spider相关推荐
- CUDA C 纹理提取Texture Fetching
CUDA C 纹理提取Texture Fetching 一.参数曲面的纹理 使用纹理指定参数曲面属性. 二.CUDA C 纹理获取开发 用于计算纹理函数,根据纹理引用的各种属性返回的值的公式(请参见纹 ...
- Python:Spider
Spider类定义了如何爬取某个(或某些)网站.包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item). 换句话说,Spider就是您定义爬取的动作及分析某个网页( ...
- 风格化手绘纹理包 CGTrader – Stylized Mix Vol. 41 – Hand Painted Texture Pack
风格化手绘纹理包 CGTrader – Stylized Mix Vol. 41 – Hand Painted Texture Pack CGTrader–风格化混合第41卷–手绘纹理包 大小解压后: ...
- 使用Depth Texture
使用Depth Textures: 可以将depth信息渲染到一张texture,有些效果的制作会需要scene depth信息,此时depth texture就可以派上用场了. Depth Text ...
- R语言使用ggradar包可视化基本雷达图(radar chart、蜘蛛图spider plot)、可视化单个数据对象的雷达图
R语言使用ggradar包可视化基本雷达图(radar chart.蜘蛛图spider plot).可视化单个数据对象的雷达图 目录
- R语言使用ggradar包可视化基本雷达图(radar chart、蜘蛛图spider plot)、可视化单个数据对象的雷达图、自定义雷达图的线条类型、线条宽度、数据点大小、色彩等
R语言使用ggradar包可视化基本雷达图(radar chart.蜘蛛图spider plot).可视化单个数据对象的雷达图.自定义雷达图的线条类型.线条宽度.数据点大小.色彩等(Customize ...
- R语言使用fmsb包、gradar包可视化雷达图(radar chart、蜘蛛图spider plot)、ggpubr包可视化点图、GGally包可视化多变量的平行坐标轴图
R语言使用fmsb包.gradar包可视化雷达图(radar chart.蜘蛛图spider plot).ggpubr包可视化点图.GGally包可视化多变量的平行坐标轴图 目录
- opengl地球贴纹理_一文看懂材质/纹理 Material, Texture, Shading, Shader 的区别
在计算机图形学和三维设计中,有几个容易混淆的概念.今天我们来一举拿下. 概念整理 可以这么总结: Material 是表现 Shading 的数据集.其他几个概念都是生成这一数据集的资源或者工具. 这 ...
- kivy texture图片格式和opencv numpy图片格式互转
# 将Texture格式的图片对象转换为numpydef texture_to_numpy(self,data):image=numpy.asarray(bytearray(data.pixels), ...
最新文章
- centos6.5离线安装gcc gcc++ rpm
- pip 代理设置,坑爹的代理继续
- 观察者模式C#实现实例(一)
- velocimeter-view android测速仪效果
- Python程序练习题6.2
- 计算机复试通知学校,提醒:部分学校复试通知已经出了!教育部关于21考研复试的规定!...
- vue 点击div 获取位置_vue 点击元素滚动到指定位置
- 字符串固定长度 易语言_易语言宽字符数据类型怎么设置
- Java Main Differences between HashMap HashTable and ConcurrentHashMap
- 《程序设计技术》第九章例程
- 我误会atoi()函数了
- WebStorm和VSCode配置
- 简易波形发生器通过单片机的Proteus仿真
- ubuntu18.04键盘背光灯以及Scroll Lock建失效
- 银行客户违约信息分析(数据挖掘)
- 飞机机身结构主要分三种,现在大部分飞机都用第三种
- 比较全面的log4j配置
- cgroup使用举例和linux内核源码详解
- 神经网络与深度学习(一)——机器学习基础
- ipad一直显示连接app服务器出错,iPad显示无法连接到App Store怎么办 打开不了解决方法...
热门文章
- iOS小技能:SKU视图搭建
- Docker构建harbor+IDEA,一篇文章就够了
- 【小工具】- Ubuntu如何查看cpu支持的指令集
- python列表输出学生姓名学号链表_c语言!!!程序设计:建立一个学生信息链表,包括学号,姓名,成绩.(实现添加,删除,查询,排序,平均)...
- js修改伪元素的属性、styleSheets获取样式表,Failed to read the 'cssRules' property from 'CSSStyleSheet' Cannot acces
- BZOJ1022: [SHOI2008]小约翰的游戏John
- 1 dB压缩点_噪声系数_小信号非线性的数学描述
- 中国卸油系统行业市场供需与战略研究报告
- 两条命令让你的git轻松自动变基,学到了!
- Mysql-Cluster 集群部署