Python的zlib/gzip解压CommonCrawl的wet.gz文件仅返回部分内容?
Python解压CommonCrawl wet.gz文件内容不完整问题
从CommonCrawl下载了100MB的wet.gz文件,用终端gunzip命令解压完全正常,输出开头内容如下:
WARC/1.0 WARC-Type: warcinfo WARC-Date: 2022-08-20T09:26:35Z WARC-Filename: CC-MAIN-20220807150925-20220807180925-00000.warc.wet.gz WARC-Record-ID: <urn:uuid:3f9035e8-8038-4239-a566-c9410b93956d> Content-Type: application/warc-fields Content-Length: 371 Software-Info: ia-web-commons.1.1.10-SNAPSHOT-20220804021208 Extracted-Date: Sat, 20 Aug 2022 09:26:35 GMT robots: checked via crawler-commons 1.4-SNAPSHOT (https://github.com/crawler-commons/crawler-commons) isPartOf: CC-MAIN-2022-33 operator: Common Crawl Admin (info@commoncrawl.org) description: Wide crawl of the web for August 2022 publisher: Common Crawl WARC/1.0 WARC-Type: conversion WARC-Target-URI: http://100bravert.main.jp/public_html/wiki/index.php?cmd=backup&action=nowdiff&page=Game_log%2F%EF%BC%A7%EF%BC%AD%E6%9F%98&age=53 WARC-Date: 2022-08-07T15:32:56Z WARC-Record-ID: <urn:uuid:8dd329bf-6717-4d0c-ae05-93445c59fd50> WARC-Refers-To: <urn:uuid:1e2e972b-4273-468a-953f-28b0e45fb117> WARC-Block-Digest: sha1:GTEJAN2GXLWBXDRNUEI3LLEHDIPJDPTU WARC-Identified-Content-Language: jpn Content-Type: text/plain Content-Length: 12482 Game_log/GM柘 のバックアップの現在との差分(No.53) - PukiWiki Game_log/GM柘 のバックアップの現在との差分(No.53) [ トップ ] [ 新規 | 一覧 | 単語検索 | 最終更新 | ヘルプ ] バックアップ一覧
但用Python的gzip或zlib库解压时,返回结果只有开头部分,后续内容丢失,代码示例如下:
# using gzip fh = gzip.open('wet.gz', 'rb') data = fh.read(); fh.close() # using zlib o = zlib.decompressobj(zlib.MAX_WBITS|16) result = [] result = [o.decompress(open("wet.gz", "rb").read()), o.flush()]
这是Python的zlib/gzip库存在bug吗?
解决方案
这不是Python库的bug,问题出在一次性读取大文件并解压的方式。100MB的压缩文件解压后体积会远超出常规内存承载范围,一次性读取会导致内存溢出或内容截断,只保留部分数据。正确的做法是分块读取并逐步解压:
原生Python分块处理示例
import gzip # 分块读取并解压,每次处理1MB数据 with gzip.open('wet.gz', 'rb') as f: while True: chunk = f.read(1024 * 1024) if not chunk: break # 按需处理当前块,比如打印或写入文件 print(chunk.decode('utf-8'), end='')
简化封装方案
如果不想自己实现分块逻辑,可以使用已封装好的工具库:
- 安装依赖:
pip install k1lib
- 使用示例:
from k1lib.imports import * lines = cat("wet.gz", text=False, chunks=True) | unzip(text=True) for line in lines: print(line)
这段代码会以二进制模式分块读取文件,逐步解压后分割为多行并转换为字符串。
内容的提问来源于stack exchange,提问作者157 239n
相关产品推荐
相关产品推荐

