爬取一个超大级规划图的历程,嗯,有点坑。Python实现,低配电脑多线程方案。

本文主要是介绍爬取一个超大级规划图的历程,嗯,有点坑。Python实现,低配电脑多线程方案。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

         三天前,在一个Python技术交流群里面,一个朋友发出了一条消息,说爬取一个网站的放大级别最大的图,爬取下来。而且是有偿,当时我就想,这个地图我应该可以试试,然后点击网址(当时把网址也一起发出来了)然后放大到最大,看了一下,感觉不会太好爬取,然后我就问跟他私聊了一下,想试一下,如果有比我速度更快的请跟我说,我先分析一下,看看多久能爬去完。跟他说了以后,就开始分析网页,然后一点一点的抓取网页内的各种资源信息,一点一点的分析看看哪一些是我需要的资源。
          我的分析思路是这样的:
点进网址看到的是这样的,分析网页元素:

现在需要我做的就是将地图色块放大到最大,然后将整张图片下载下来。
然后我就看,这个网页的元素不算太多,会不会是用js控制div显示的图片呢?然后我继续分析网页,看到有一个iframe标签,,将鼠标放在上面好,正好在网页中是地图的区域,果断用链接进去,看到的网页是这样的。

这一下把好多没用的网页标签元素都去掉了,让人眼前一清晰,然后继续上面那一步,开始分析网页元素,用浏览器的Select an Element in the Page (快捷键ctrl+shift+C)然后定位到一个svg标签,这不是定义用于网络的基于矢量的图形的标签吗?果断进去看每个标签分析,然后继续用select an element 里面的但是,进去后,啥也没有啊,

而且根据里面的分析,还是一个hidden的svs   下面的g标签也是“display:block”的,很明显没显示啊,估计是用来故意防止反爬的吧,但是看到图片就在眼前不可能没有数据接口啊。所以我继续努力分析,
点开network以后发现里面又好多png的图片啊,

这应该是我所想要的图片了吧,我将图片打开,点开之后是一个下载地址,嗯,果断下载下来看一下,还真让我找到了,还真是,不过是缩小到最小的图的一部分,我然后将他放大以后再试试,放大以后,继续点开图片,下载,是我想要的图,但是,下载下来不是一整张图,而是一整张图的一小块。这就很尴尬了,放大到这么大,然后下载下来的图片只有这一小部分,这就有点尴尬了。虽然找到图了,但是对于一整张下载下来的话,得有多少张这样小的图呢?而且,从左上角开始分析,第一张图里面的并没有什么东西啊。有点小难度啊。
然后我开始跟那兄弟沟通,是不是只需要有色块的就可以,红线的就可以不需要了?经过一系列的沟通获取同意后,然后我开始测试,分析网站地址http://27.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/tile/1/1051/1463 后边的数保留,每次下载的图片都是最后数的数值为名称的png图片,我把数字简单修改以后,一样也可以下载,但是那么大的图,肯定不可能以前多张,是不是倒数二级目录也可以修改下载呢?这样我就下载了一下1050/1463    1051/1463      1050/1462   这三个地址所对应的图片,然后根据图片分析,倒数第二个目录代表y轴最后一级的目录代表的是x轴,所以,倒数第三个目录又是什么?我放大缩小之后查看network里面png所对应的地址,发现,当第三级有1-9个,当到了9的时候也就说明图片级别最大了。所以我将地图放大到9级然后,查看色块区域,这里我又返回到了element里面查看元素,既然又图片肯定应该有img标签元素或者是其他标签元素来将图片显示吧?经过我的努力分析还真让我给找到了。
就在svg标签上一层的div标签里面。既然人家需要有色块的区域内,那我就将这一块区域内上下左右的最靠边的四张图片的xy轴所对应的目录级别找到就可以了啊。将整个有色区域开始圈在一个矩形内。
找到后,好了,分析完成了,那我们就开始写代码吧。由于考虑到分析不全,怕上下左右找到的不是最靠边的,所以我就分别往外为扩展了一下,找到的坐标分别是上(187228,134402)下(187167,134620)左(187122,134455)右(187380,134539),我的天呢。这样一算,大概需要220*260张图片,大概57200张图片,根据测试下载下来的图片宽高像素都是256,这样一算,图片不小啊。

然后开始写代码,由于前面主要的分析思路已经完成了,现在主要就是访问图片地址获取图片就可以了。
好了,开始我的代码表演,直接上Request模块,都不需要用bs4或者是selenium模块的,因为直接获取的就是图片。

导入模块:

import threading
import time
from urllib import request
from urllib import error
import os
import socket

定义函数,ypx为Y轴。xpx为X轴。从上往下开始,横向下载,当没行x爬取完成后会y加一,然后继续爬取,当然了,是一行一行爬取的,所以我就需要每一行都要保存在一个文件加下面,就以y轴为名称,建立文件夹,保存在里面吧。
 

def mian(ypx,n):   #url8 = '资源网址/tile/8/'headers = {"Referer": "资源网址/map.html","User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}path = "I:\map"xpx = 187121 #121y = ypx+3socket.setdefaulttimeout(30)while True:num = 0while True:try:if xpx < 187382:url = url8 + str(ypx) + "/" + str(xpx)print(n,"线程的下载",url)try:req = request.Request(url, headers=headers)html = request.urlopen(req)savePng(mkdirAndReturnNmae(path + "\\" + str(ypx), xpx), html.read())html.close()xpx += 1time.sleep(1)num = 1except ConnectionResetError  as  rese:print(n,rese)xpx -= 1time.sleep(5)print(n,"————————————————————————————————————————等待五秒。。。。")continueexcept socket.timeout as  stout:print(n,stout)xpx -= 1time.sleep(5)print(n,"————————————————————————————————————————等待五秒。。。。")continueexcept TimeoutError as  timeout:print(n, timeout)xpx -= 1time.sleep(5)print(n, "————————————————————————————————————————等待五秒。。。。")continueelse:xpx = 187121breakexcept error.HTTPError as e:print(n,"HttpError 跳过 ", e)time.sleep(0.5)xpx += 1print(n , "线程    ",xpx)# html.close()if num == 1:xpx = 187121break# continueypx += 1if ypx >= y:print(n,"线程  即将结束 ",ypx)print(n,".。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。请求结束。。。。。")exit(0)time.sleep(1)

嗯,因为考虑到服务器端那边可能会防止爬取,所以,每次获取一次图片,都会sleep(1),因为这么高强度,持续性的获取图片,服务器可能会认为是恶意攻击,所以,会有ConnectionResetError的错误(就是服务器强制断开链接),避免出现这个错误,利用try except 避免,except执行的函数,当出现这个错误的时候,会x轴返回一个,然后,sleep(5),,continue继续执行,而且,在服务器的reponse的返回后,获取完了图片要close()一下。这样可以在一定程度上避免服务器强制断开链接。在运行的时候,多次遇到TimeoutError,所以我导入了socket模块,设置一下等待时间socket.setdefaulttimeout(30),好像是我设置位置的问题,并没有有效避免这个问题,经常被except捕获到TimeoutError。所以在时间上,有很大程度的限制。嗯,避免这些问题以后,就开始爬取了,但是我的电脑配置有点底呀,而且,自己也没有服务器,分布式爬虫运用的现在也不太好,我就考虑运用多线程爬取。不过效果还行,如果是单线程话,五万多张近六万张图片每个sleep(1)一下,排除其他因素对时间的影响,还需要16个小时呢。如果多开几个线程的话,应该能够可以有效的节约一定的时间吧。所以,导入threading模块。
自定义线程类,继承thread类:
 

class MyThread(threading.Thread):"""属性:target: 传入外部函数, 用户线程调用args: 函数参数"""def __init__(self, target, args,krgs):super(MyThread, self).__init__()  # 调用父类的构造函数self.target = targetself.args = argsself.krgs= krgsdef run(self):self.target(self.args,self.krgs)

由于不需要太多的其他处理,所以简单定义一下。

下面是定义多个线程,开始线程的函数:
 

def main():mh1 = MyThread(mian,134599,1)  #574 开始+10mh2 = MyThread(mian,134602,2)  #584mh1.start()mh2.start()k=time.time()

 




好了,下面的代码是创建目录保存图片data的函数,自行了解就好。
 

def mkdirAndReturnNmae(path, idname):  # 创建保存目录并返回保存路径及名称if os.path.isdir(path):name = os.path.join(path, str(idname) + ".png")return nameelse:os.mkdir(path)name = os.path.join(path, str(idname) + ".png")return name

保存data

def savePng(name, data):file = open(name, 'wb')file.write(data)# print(name)file.close()


经过多层分析,以及处理,用我的小电脑用了三个多小时爬取下来了这些图片。

 

可是又有一个问题,需要我处理,我的电脑配置有点低,我应该怎么给他合成呢?有点难度,但是,通过查看前辈们的博客,还是找到了处理方法。下一篇文章继续写。爬取这一块已经完成。如果有更好的处理方法的话,还请大佬们多多赐教。小弟在这里提前感谢一下。

 

 

这篇关于爬取一个超大级规划图的历程,嗯,有点坑。Python实现,低配电脑多线程方案。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Python实现精确小数计算的完全指南

《Python实现精确小数计算的完全指南》在金融计算、科学实验和工程领域,浮点数精度问题一直是开发者面临的重大挑战,本文将深入解析Python精确小数计算技术体系,感兴趣的小伙伴可以了解一下... 目录引言:小数精度问题的核心挑战一、浮点数精度问题分析1.1 浮点数精度陷阱1.2 浮点数误差来源二、基础解决

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

Java实现远程执行Shell指令

《Java实现远程执行Shell指令》文章介绍使用JSch在SpringBoot项目中实现远程Shell操作,涵盖环境配置、依赖引入及工具类编写,详解分号和双与号执行多指令的区别... 目录软硬件环境说明编写执行Shell指令的工具类总结jsch(Java Secure Channel)是SSH2的一个纯J

使用Python实现Word文档的自动化对比方案

《使用Python实现Word文档的自动化对比方案》我们经常需要比较两个Word文档的版本差异,无论是合同修订、论文修改还是代码文档更新,人工比对不仅效率低下,还容易遗漏关键改动,下面通过一个实际案例... 目录引言一、使用python-docx库解析文档结构二、使用difflib进行差异比对三、高级对比方

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

详解python pycharm与cmd中制表符不一样

《详解pythonpycharm与cmd中制表符不一样》本文主要介绍了pythonpycharm与cmd中制表符不一样,这个问题通常是因为PyCharm和命令行(CMD)使用的制表符(tab)的宽... 这个问题通常是因为PyCharm和命令行(CMD)使用的制表符(tab)的宽度不同导致的。在PyChar

QT Creator配置Kit的实现示例

《QTCreator配置Kit的实现示例》本文主要介绍了使用Qt5.12.12与VS2022时,因MSVC编译器版本不匹配及WindowsSDK缺失导致配置错误的问题解决,感兴趣的可以了解一下... 目录0、背景:qt5.12.12+vs2022一、症状:二、原因:(可以跳过,直奔后面的解决方法)三、解决方

MySQL中On duplicate key update的实现示例

《MySQL中Onduplicatekeyupdate的实现示例》ONDUPLICATEKEYUPDATE是一种MySQL的语法,它在插入新数据时,如果遇到唯一键冲突,则会执行更新操作,而不是抛... 目录1/ ON DUPLICATE KEY UPDATE的简介2/ ON DUPLICATE KEY UP