Mercurial > hg > cc > cirrus_work
changeset 320:c68714dee9f2 trim
centralise all need for new approach to cdb index shrinking in one place
| author | Henry S. Thompson <ht@inf.ed.ac.uk> |
|---|---|
| date | Tue, 20 Jan 2026 19:46:48 +0000 |
| parents | 439cbfd6cbda |
| children | cf50a54b8b53 |
| files | lib/python/cc/lmh/cdb_one.py lib/python/cc/lmh/shrink.py lib/python/cc/lmh/shrink_key.py lib/python/cc/lmh/warc2cdb.py |
| diffstat | 4 files changed, 64 insertions(+), 81 deletions(-) [+] |
line wrap: on
line diff
--- a/lib/python/cc/lmh/cdb_one.py Fri Jan 16 17:12:33 2026 +0000 +++ b/lib/python/cc/lmh/cdb_one.py Tue Jan 20 19:46:48 2026 +0000 @@ -12,6 +12,7 @@ ''' import cython, typing, timeit, re, sys, array +import shrink_key from db import CCdb @@ -55,16 +56,7 @@ N += 1 seg = int(segb) if (seg >= S and seg < E): - # See shrink.py l. 27ff for this shrinkage - for i in range(dpl): - if wdate[i] != DP[i]: - break - else: - i+=1 - if i > 0: - nd = wdate[i:] - else: - nd = DP + nd = shrink_key.shrink_date(wdate, DP) if kind == 'robotstxt': nd += seg if not uri.startswith(b'http'):
--- a/lib/python/cc/lmh/shrink.py Fri Jan 16 17:12:33 2026 +0000 +++ b/lib/python/cc/lmh/shrink.py Tue Jan 20 19:46:48 2026 +0000 @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# cython: profile=False, language_level=3str '''Shrink cdb_input-style files after the fact Each record is encoded as +klen,dlen:key->data @@ -6,6 +7,8 @@ ''' import sys, io +import shrink_key + ifn = sys.argv.pop(1) dp = sys.argv.pop(1).encode('ascii') ofn = sys.argv.pop(1) @@ -24,26 +27,13 @@ kl=int(os1) ll=int(os2) #print(od,dp,dpl,file=sys.stderr) - for i in range(dpl): - if od[i] != dp[i]: - break - else: - i+=1 - if i > 0: - nd = od[i:] - else: - nd = od - #print(i,od,nd,file=sys.stderr) ol = oe[-ll:] - nli = int(ol) - bad = (nli < 0 or nli > 2147483647) - of.write(b'+%d,%d'%(kl-(len(od)-len(nd)),len(ol) if bad else 4)) + (nd,nlb)=shrink_key.shrink_date(od,dp,ol) + #print(i,od,nd,'%x'%nlb,file=sys.stderr) + of.write(b'+%d,%d'%(kl-(len(od)-len(nd)),len(nlb))) of.write(b':') of.write(nd) of.write(b':') - of.write(oe[:-ll]) - if bad: - of.write(ol) - else: - of.write(int.to_bytes(nli,4)) + of.write(oe[:-ll]) # includes the -> + of.write(nlb) of.write(b'\n')
--- a/lib/python/cc/lmh/shrink_key.py Fri Jan 16 17:12:33 2026 +0000 +++ b/lib/python/cc/lmh/shrink_key.py Tue Jan 20 19:46:48 2026 +0000 @@ -15,24 +15,10 @@ C_PAT: typing.Pattern[bytes] = re.compile(b'[^ ]* ([^ ]*) .*{"url": "(http[^"]*).*"filename": "[^"]*[.]([0-9][0-9]?)/(warc|robotstxt|crawldiagnostics)/') -def shrink(entry: bytes, dp: bytes) -> bytes: - m: typing.Match[bytes] | None - +def shrink_date(wdate: bytes, dp: bytes, lmb: bytes) -> tuple[bytes,bytes]: dpl: int = len(dp) - uri: bytes - wdate: bytes - kind: bytes - segb: bytes - ts: array.array - seg: int - res: int i: int - nd: bytes - if (m:=C_PAT.match(entry)): - (wdate, uri, segb, kind) = m.groups() - else: - raise ValueError(l) - seg = int(segb) + lm: int for i in range(dpl): if wdate[i] != dp[i]: break @@ -42,16 +28,36 @@ nd = wdate[i:] else: nd = dp - if kind == 'robotstxt': - nd += seg - if not uri.startswith(b'http'): - raise ValueError(uri) + lm = int(lmb) + if (lm >= 0 and lm <= 2147483647): + lmb=int.to_bytes(lm,4) #print(nd,uri[4:],file=sys.stderr) - return nd+uri[4:] + return (nd,lmb) if __name__ == "__main__": + m: typing.Match[bytes] | None cdx_in: typing.BinaryIO = sys.stdin.buffer l: bytes DP: bytes = sys.argv[1].encode('ASCII') + uri: bytes + wdate: bytes + kind: bytes + segb: bytes + ts: array.array + seg: int + res: int + nd: bytes + nv: bytes for l in cdx_in: - sys.stdout.buffer.write(shrink(l,DP)) + if (m:=C_PAT.match(l)): + (wdate, uri, segb, kind) = m.groups() + else: + raise ValueError(l) + (nd,nv) = shrink_date(wdate,DP,'0') + seg = int(segb) + if kind == 'robotstxt': + nd += seg + if not uri.startswith(b'http'): + raise ValueError(uri) + sys.stdout.buffer.write(nd+uri[4:]) + sys.stdout.buffer.write(b'\n')
--- a/lib/python/cc/lmh/warc2cdb.py Fri Jan 16 17:12:33 2026 +0000 +++ b/lib/python/cc/lmh/warc2cdb.py Tue Jan 20 19:46:48 2026 +0000 @@ -1,13 +1,18 @@ #!/usr/bin/env python3 +# cython: profile=False, language_level=3str '''Produce cdb_input-style files from warc responses with lmh header value - Usage: warc2cdb.py CC-date segment output-dir warc_file_type warc_file_range lm_shrink_prefix cdate_shrink_prefix ''' + Usage: warc2cdb.py CC-date segment output-dir warc_file_type warc_file_range cdate_base + warc_file_type is warc|robotstxt|crawldiagnostics + warc_file_range is (literally) '???' or from,to + cdate_base is the most likely complete (14-digit) warc-crawl-date''' import re, warc, sys, glob, codecs, os.path import cython, typing import email.utils from urllib.parse import quote import subprocess +import shrink_key TUPAT: typing.Pattern[bytes] = re.compile(b'^WARC-Target-URI: (.*?)\r?$',re.MULTILINE) DPAT: typing.Pattern[bytes] = re.compile(b'^WARC-Date: (.*?)\r?$',re.MULTILINE) @@ -23,22 +28,24 @@ URI: bytes DATE: bytes +LM: bytes WIN: int = 0 LOSE: int = 0 N: int = 0 UERRS: int = 0 NON_HTTP: int = 0 -NON_MONTH: int = 0 -NON_ERA: int = 0 -def _u_esc(c): +C_BASE: bytes +C_BASE_L: int + +def _u_esc(c: int) -> str: if c<65536: return '\\u%04X'%c else: return '\\U%08X'%c -def java_unicode_encode(ude): +def java_unicode_encode(ude: Type[UnicodeDecodeError]) -> tuple[str,int]: '''like backslashreplace but use uppercase and \\ u00NN instead of \\ xnn''' return (''.join(_u_esc(ord(c)) for c in ude.object[ude.start:ude.end]), ude.end) @@ -47,8 +54,8 @@ def LMHline(wtype: int, buf: memoryview, part: int) -> None: global TUPAT, DPAT, LMPAT, FFPAT, DTAB, DDEL, OUT, WIN, LOSE, NON_HTTP, NON_MONTH - global N, UERRS, SEG, R_T, LM_ERA, LM_ERA_L, C_MONTH, C_MONTH_L, NON_ERA - global DATE, URI + global N, UERRS, SEG, R_T, C_BASE, C_BASE_L + global DATE, URI, LM m: typing.Match[cython.bytes] | None mm: typing.Match[cython.bytes] | None lmi: cython.bytes @@ -72,11 +79,6 @@ try: try: lmi = b'%d'%int(email.utils.parsedate_to_datetime(dateTime.decode('utf8')).timestamp()) - if LM_ERA: - if lmi.startswith(LM_ERA): # save 2 bytes in ~80% of cases - lmi=b'0'+lmi[LM_ERA_L:] - else: - NON_ERA += 1 except OverflowError: lmi = b'32535215999' except (TypeError,IndexError,ValueError) as e: @@ -84,11 +86,7 @@ LOSE += 1 return DATE=(DATE.translate(DTAB,DDEL)) - if C_MONTH: - if DATE.startswith(C_MONTH): - DATE=DATE[C_MONTH_L:] - else: - NON_MONTH += 1 + (DATE,LM) = shrink_key.shrink_date(DATE,C_BASE,lmi) WIN += 1 try: URI.decode('ascii') @@ -101,7 +99,7 @@ URI=URI[4:] else: NON_HTTP += 1 - l: int = len(lmi) + l: int = len(LM) kl: int = (len(DATE)+len(URI)+(len(SEG) if R_T else 0)) OUT.write(b'+') OUT.write(b'%d'%kl) @@ -113,28 +111,25 @@ OUT.write(SEG) OUT.write(URI) OUT.write(b'->') - OUT.write(lmi) + OUT.write(LM) OUT.write(b'\n') -def main(CCdate, segment, outdir, subdir = 'warc', fpat = None, era = '', month = '' ): +def main(CCdate: str, segment: str, outdir: str, subdir: str, fpat: str, dp: str ): global OUT, N, WIN, LOSE, UERRS, SEG, R_T - global NON_HTTP, C_MONTH, C_MONTH_L, NON_MONTH, LM_ERA, LM_ERA_L, NON_ERA + global NON_HTTP, C_BASE, C_BASE_L SEG = segment.encode('utf8') R_T = (subdir == 'robotstxt') - LM_ERA = era.encode('utf8') - LM_ERA_L = len(era) - C_MONTH = month.encode('utf8') - C_MONTH_L = len(month) - infile_pat='bash -c "ls $CCC/CC-MAIN-%s/*.%s/orig/%s/*00%s.warc.gz | sort -k8"'%( - CCdate, segment, subdir, ("???" if fpat is None else ( - (("{%s..%s}"%tuple(fpat.split(','))) if ',' in fpat else fpat)))) - + C_BASE = dp.encode('ascii') + C_BASE_L = len(dp) + if fpat != '???': + fpat = ("{%s..%s}"%tuple(fpat.split(','))) if ',' in fpat else fpat + infile_pat='bash -c "ls $CCC/CC-MAIN-%s/*.%s/orig/%s/*00%s.warc.gz | sort -k8"'%(CCdate, segment, subdir, fpat) with open((outfile_name:="%s/%s/%s/lmh.cdb_in"%(outdir, segment, subdir)),'wb') as OUT: for infile_name in subprocess.run(infile_pat, shell=True, stdout=subprocess.PIPE).stdout.decode('utf8').split(): print(infile_name,file=sys.stderr) - WIN = LOSE = N = UERRS = NON_HTTP = NON_MONTH = NON_ERA = 0 + WIN = LOSE = N = UERRS = NON_HTTP = 0 if subdir in ['warc','robotstxt']: warc.warc(infile_name,LMHline,[warc.RESP],parts=3) elif subdir == 'crawldiagnostics': @@ -142,7 +137,7 @@ else: print('bogus type %s'%subdir,file=sys.stderr) exit(1) - print('%d LM headers, %d win, %d lose, %d non-ASCII URIs, %d non-close, %d dodgy schemes, %d dodgy WARC dates'%(N,WIN,LOSE,UERRS,NON_ERA,NON_HTTP,NON_MONTH), + print('%d LM headers, %d win, %d lose, %d non-ASCII URIs, %d dodgy schemes'%(N,WIN,LOSE,UERRS,NON_HTTP), file=sys.stderr) OUT.write(b'\n')
