zipfile.Zipfile открыть определенный файл в папке Zip - PullRequest
0 голосов
/ 11 октября 2019

Я новичок в Python и пытаюсь создать программу, которая загружает и извлекает zip-файлы с различных веб-сайтов. Я вставил две программы, которые я написал, чтобы сделать это. Первая программа - это «дочерняя» программа с именами «urls», которую я импортирую во вторую программу. Я пытаюсь перебрать каждый из URL-адресов, и внутри каждого URL-адреса перебрать каждый файл данных, и, наконец, проверить, является ли список «ключевых слов» частью имени файла, и если да, загрузить и извлечь этот файл. Я застреваю в той части, где мне нужно перебрать список «ключевых слов», чтобы проверить имена файлов, которые я хочу скачать. Вы могли бы помочь? Я ценю любые ваши предложения или рекомендации. Спасибо. Энди

**Program #1 called "urls":**

urls = [
    "https://www.dentoncad.com/content/data-extracts/1-appraisal-data-extracts/1-2019/1-preliminary/2019-preliminary" \
    "-protax-data.zip",
    "http://www.dallascad.org/ViewPDFs.aspx?type=3&id=//DCAD.ORG\WEB\WEBDATA\WEBFORMS\DATA%20PRODUCTS\DCAD2020_" \
    "CURRENT.ZIP"
]

keywords = [
    "APPRAISAL_ENTITY_INFO",
    "SalesExport",
    "account_info",
    "account_apprl_year",
    "res_detail",
    "applied_std_exempt",
    "land",
    "acct_exempt_value"
]`enter code here`

    enter code here

**Program #2 (primary program):**

import requests
import zipfile
import os
import urls


def main():
    print_header()
    dwnld_zfiles_from_web()


def print_header():
    print('---------------------------------------------------------------------')
    print('               DOWNLOAD ZIP FILES FROM THE WEB APP')
    print('---------------------------------------------------------------------')
    print()


def dwnld_zfiles_from_web():
    file_num = 0

    dest_folder = "C:/Users/agbpi/OneDrive/Desktop/test//"

    # loop through each url within the url list, assigning it a unique file number each iteration
    for url in urls.urls:
        file_num = file_num + 1
        url_resp = requests.get(url, allow_redirects=True, timeout=5)

        if url_resp.status_code == 200:
            saved_archive = os.path.basename(url)
            with open(saved_archive, 'wb') as f:
                f.write(url_resp.content)

                # for match in urls.keywords:

                print("Extracting...", url_resp.url)

                with zipfile.ZipFile('file{0}'.format(str(file_num)), "r") as z:
                    zip_files = z.namelist()
                    # print(zip_files)
                    for content in zip_files:
                        while urls.keywords in content:
                            z.extract(path=dest_folder, member=content)
                    # while urls.keywords in zip_files:
                    #     for content in zip_files:
                    #         z.extract(path=dest_folder, member=content)

                print("Finished!")


if __name__ == '__main__':
    main()

1 Ответ

0 голосов
/ 13 октября 2019

Хорошо, обновленный ответ основан на обновленном вопросе.

Ваш код в порядке до этой части:

                with zipfile.ZipFile('file{0}'.format(str(file_num)), "r") as z:
                    zip_files = z.namelist()
                    # print(zip_files)
                    for content in zip_files:
                        while urls.keywords in content:
                            z.extract(path=dest_folder, member=content)

Выпуск 1

Выимя zip-файла уже имеет значение saved_archive, но вы пытаетесь открыть что-то еще в виде zip-файла. Почему 'file{0}'.format(str(file_num))? Вы должны просто with zipfile.ZipFile(saved_archive, "r") as z:

Issue 2

while является своего рода оператором if, но он не работает как фильтр (кажется, выхотел этого). Что делает while, так это то, что он проверяет, является ли условие оператора (после части while) True -ish, и если да, то выполняет код с отступом. И как только начинается первая False -я оценка, выполнение кода продолжается. Поэтому, если ваша оценка состояния выдаст эти результаты [True, False, True], первый вызовет запуск кода с отступом, второй приведет к выходу, а третий будет проигнорирован из-за предыдущего условия выхода. Но условие недействительно, что приводит к:

Выпуск 3

url.keywords - это list, а content - это str. Список в строке никогда не будет иметь смысла. Это как ['apple', 'banana'] in 'b'. 'b' не будет таких членов. Вы можете изменить логику, но имейте в виду, что 'b' in ['apple', 'banana'] будет False, 'banana' in ['apple', 'banana'] будет True.

Это означает, что в вашем случае это условие: '_SalesExport.txt' in urls.keywords будет False! Почему? Поскольку url.keywords - это:

[
    "APPRAISAL_ENTITY_INFO",
    "SalesExport",
    "account_info",
    "account_apprl_year",
    "res_detail",
    "applied_std_exempt",
    "land",
    "acct_exempt_value"
]

, а SalesExport - это , а не _SalesExport.txt.

. Чтобы выполнить частичную проверку соответствия, необходимо сравнить элементы списка (строки) против строки. "SalesExport" in "_SalesExport.txt" - это True, но "SalesExport" in ["_SalesExport.txt"] - это False, поскольку SalesExport не является членом списка.

Вы можете сделать три вещи:

  1. обновить список keywords, указав точные имена файлов, чтобы content in kw_list мог работать (это означает, что если вZIP-файл, вы должны включить его тоже)
                    for content in zip_files:
                        if content in urls.keywords:
                            z.extract(path=dest_folder, member=content)
реализовать цикл for для цикла
                    for content in zip_files:
                        for kw in urls.keywords:
                            if kw in content:
                                z.extract(path=dest_folder, member=content)
используйте генератор
matches = [x for x in zip_files if any(y for y in urls.keywords if y in x)]
for m in matches:
    z.extract(path=dest_folder, member=m)


Наконец, рекомендация:

Таймауты

Будьте осторожны с

url_resp = requests.get(url, allow_redirects=True, timeout=5).

«Тайм-аут» контролирует две вещи: тайм-аут соединения и тайм-аут чтения. Поскольку ответ может занять более 5 секунд, вы можете захотеть увеличить время ожидания чтения. Вы можете указать время ожидания как кортеж: (время ожидания соединения, время ожидания чтения). Поэтому лучшим параметром будет:

url_resp = requests.get(url, allow_redirects=True, timeout=(5, 120))

...