Python如何在https上搜索驻留在iframe中的zip文件

2024-09-29 19:29:34 发布

您现在位置:Python中文网/ 问答频道 /正文

  • Python-2.7.5
  • 谷歌Chrome

首先,我是自学程序员,并将接受任何批评和/或建议,我张贴的任何代码下面。这个问题一直是一个愉快的工作,因为我喜欢挑战自己,但我恐怕我遇到了困难,需要一些指导。我将在下面尽可能详细地解释我的剧本的整体情况,然后展示我在标题中所解释的实际问题。在

我正在编写一个脚本,它将自动下载数据、升级压缩并导出到GDB。我们为广大用户提供服务,并拥有一个非常大的企业SDE设置,其中包含大量公共数据,我们必须为最终用户搜索和更新这些数据。我们的大部分数据每月都由当地政府机构更新,我们必须出去手动搜索数据、下载、解压、QAQC等。我想把一个脚本a放在一起,通过出去下载我所有的数据并导出到本地的GDB,来自动完成这一过程的第一部分,从那里我可以QAQC的一切,并上传到我们的SDE供我们的用户访问。在

到目前为止,这个过程一直很简单,直到我解决了我面前的这个问题。我的脚本将搜索网页的特定关键字,找到相关的链接,并开始下载。对于这篇文章,我将使用两个例子,一个是有效的,一个是目前给我的问题。我的功能是搜索和下载Metro GIS数据集,下面展示了我当前的查找过程。到目前为止,我所包含的所有http网站都将使用下面的发布功能。就像Metro所展示的那样,我计划为每一组数据定义一个函数。在

import requests, zipfile, StringIO, time, arcpy, urllib2, urlparse
from BeautifulSoup import BeautifulSoup

arcpy.env.overwriteOutput = True

workPath = -- #The output GDB
timestr = time.strftime("%Y%m%d")
gdbName = "GlobalSDEUpdate_" + timestr
gdbPath = workPath + "\\" + gdbName + ".gdb"

class global_DataFinder(object):
    def __init__(self):
        object.__init__(self)
        self.gdbSetup()
        self.metro()

    def gdbSetup(self):       
        arcpy.CreateFileGDB_management(workPath, gdbName)

    def fileDownload(self, key, url, dlPath, dsName):
        page = urllib2.urlopen(url).read()
        urlList = []

        soup = BeautifulSoup(page)
        soup.prettify()

        for link in soup.findAll('a', href = True):
            if not 'http://' in link['href']:
                if urlparse.urljoin(url, link['href']) not in urlList:
                    zipDL = urlparse.urljoin(url, link['href'])
                    if zipDL.endswith(".zip"):
                        if key in zipDL:
                            urlList.append(zipDL)        

        for x in urlList:
            print x
            r = requests.get(x, stream=True)
            z = zipfile.ZipFile(StringIO.StringIO(r.content))        
            z.extractall(dlPath)        

        arcpy.CreateFeatureDataset_management(gdbPath, dsName)
        arcpy.env.workspace = dlPath
        shpList = []

        for shp in arcpy.ListFeatureClasses():
            shpList.append(shp)

        arcpy.FeatureClassToGeodatabase_conversion(shpList, (gdbPath + "\\" + dsName))

        del shpList[:]

    def metro(self):
        key = "METRO_GIS_Data_Layers"
        url = "http://www.ridemetro.org/Pages/NewsDownloads.aspx"
        dlPath = -- *#Where my zipfiles output to*  
        dsName = "Metro"

        self.fileDownload(key, url, dlPath, dsName)

global_DataFinder()

正如你在上面看到的,这是我开始使用Metro作为我的第一个测试点的方法,目前效果很好。我希望我所有的网站都会喜欢这个,但当我到联邦应急管理局时,我遇到了一个问题。在

网站National Flood Hazard Layer (NFHL) Status承载了全国许多县的漫滩数据,任何想使用它的人都可以免费获得。当你到达网站时,你会看到你可以搜索你想要的县,然后表格查询出搜索结果,然后你可以简单地点击并下载你想要的县。在检查源代码时,我发现它是在iframe中发现的。在

当通过Chrome访问iframe源链接并检查png源url时,您将得到-https://hazards.fema.gov/femaportal/NFHL/searchResult

这里是我的问题所在,与http站点不同,我很快就了解到访问安全的https站点和抓取页面是不同的,尤其是当它使用javascript显示表时。我花了几个小时在论坛上搜索,并尝试了不同的python包,如selenium、mechanize、requests、urllib、urllib2,在安全地建立连接、解析网页和搜索我的郡zipfile之前,我似乎总是遇到了一个死胡同。下面的代码显示了我得到的最近的代码,并显示了我得到的错误代码。在

(我总是在一个单独的脚本中测试,当它工作时,我把它带到我的主脚本中,所以下面的代码片段与我的原始代码片段分开)

^{pr2}$

运行此测试时出现错误

urllib2.URLError:urlopen error[Errno 6]\u ssl.c:504:TLS/ssl连接已关闭

我希望一个更有经验的程序员可以看到我做了什么,并告诉我,如果我目前的方法是正确的,如果是的话,如何克服这个最后的错误,并正确地解析数据表。在

使用@crmackey进行编辑

^{3}$

我只添加了httplib并在顶部更改了HTTPConnection。允许我使用你的脚本连接到网站。现在的问题是。我在我的输出路径中我只得到了1个zip文件,而这个zip文件是空的。我检查了debug窗口中的打印源代码,它显示它正在尝试从表中下载VIRGIN ISLAND的区域zip文件,所以它看起来像是在尝试,但没有下载任何东西。在它输出一个空的zip文件之后,脚本完成并不再显示任何错误消息。我暂时删除了解压文件的行,因为它们返回了一个错误,因为文件夹是空的。在


Tags: 文件数据代码inself脚本httpurl
1条回答
网友
1楼 · 发布于 2024-09-29 19:29:34

我可以使用requests模块下载zip文件,还选择使用PyQuery而不是beautifulsoup。我认为您所面临的问题与SSL证书验证有关,如果您将verify参数设置为False,那么requests模块将允许您跳过对证书的检查。在

下面的函数将下载所有zip文件并解压,您可以从那里将shapefile导入您的geodatabase:

import requests
import os
import zipfile
from pyquery import PyQuery
from requests.packages.urllib3.exceptions import InsecureRequestWarning, InsecurePlatformWarning, SNIMissingWarning

# disable ssl warnings (we are not verifying SSL certificates at this time...future ehnancement?)
for warning in [SNIMissingWarning, InsecurePlatformWarning, InsecureRequestWarning]:
    requests.packages.urllib3.disable_warnings(warning)

def download_zips(out_path):
    url = 'http://www.floodmaps.fema.gov/NFHL/status.shtml'
    download_prefix = 'https://hazards.fema.gov/femaportal/NFHL'
    pq = PyQuery(requests.get(url, verify=False).content) #verify param important for SSL
    src = pq.find('iframe').attr('src')
    pq = PyQuery(requests.get(src, verify=False).content)
    table = pq.find('table')
    for a in table.find('a'):
        href = a.attrib.get('href')
        url = '/'.join([download_prefix, href])
        r = requests.get(url, stream=True, verify=False)
        out_zip = os.path.join(out_path, href.split('=')[-1])
        with open(out_zip, 'wb') as f:
            for chunk in r.iter_content(1024 *16): #grab 1KB at a time
                if chunk:
                    f.write(chunk)
        print 'downloaded zip: "{}"'.format(href.split('=')[-1])

        # do more stuff like unzip?
        unzipped = out_zip.split('.zip')[0]
        with zipfile.Zipfile(out_zip, 'r') as f:
            f.extractall(unzipped)

相关问题 更多 >

    热门问题