爬取一个超大级规划图的历程,嗯,有点坑。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调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景