Mercurial > hg > cc > cirrus_shared
view bin/cdx2tsv.py @ 0:a6c7f23cca94
adding callback functionality
| author | Henry S. Thompson <ht@inf.ed.ac.uk> |
|---|---|
| date | Sat, 28 Feb 2026 14:51:05 +0000 |
| parents | |
| children | ca6349278b82 |
line wrap: on
line source
#!/usr/bin/env python3 '''Extract named fields, with optional post-processing, in order, from a Common Crawl index row Field specs on command line are either an atom or a tuple of atom and expression with free variable f For example > cdx2tsv.py mime '(url,f.split(":",maxsplit=1)[0])' < xyzzy.cdx will output media type and URI scheme Note that 'key' and 'timestamp' are also available as global variables, so e.g. '(key,key.split(",")[0])' will yield the TLD. For a callback instead of printing, include -c cb-mod for a module to and within which to call init() once and the cbf function for each index line ''' import json,sys index = cbf = None while len(sys.argv)>2 and sys.argv[1][0]=='-': if sys.argv[1] == '-i': sys.argv.pop(1) index=str(int(sys.argv.pop(1))) elif sys.argv[1] == '-c': sys.argv.pop(1) cbmodname = sys.argv.pop(1) from importlib import import_module cbm = import_module(cbmodname) cbf=cbm.cbf cbm.init() else: break if len(sys.argv)>1 and sys.argv[1][0]=='-': print("""Reads index lines from stdin and extracts values from json dict part Usage: cdx2tsv.py [-i n] [-c callback-fn] fieldspecs... fieldspec is either a name or a quoted python tuple of a name and an expression with free variable f which will be evaluated with f having the field value. For example cdx2tsv.py mime '(url,f.split(":",maxsplit=1)[0])' < xyzzy.cdx will output media type and URI scheme -i n will include n, typically the index number, as 1st column -c cbfile will apply cbfile:cbf to each list of values instead of printing [this is probably a better approach than using tuple args with lots of tricky lambdas] """, file=sys.stderr) exit(1) fields=sys.argv[1:] stash={} # This can be used to save an expensive field computation for re-use: # E.g. '(filename,(lambda g:(stash.__setitem__("T1",g) or g)[3].split(".")[1])(f.split("/",maxsplit=5)))' '(filename,(stash["T1"])[4][0]) fields=[((lambda x,y:(x,eval("lambda f:%s"%y,globals())))(*(f[1:-1].split(',',maxsplit=1))) if f[0]=='(' else f) for f in fields] for l in sys.stdin: (surt,stamp,jj)=l.rstrip().split(' ',maxsplit=2) key = surt.split(')') ja=json.loads(jj) args = ((ja.get(f,'NA') if isinstance(f,str) else (f[1](ja[f[0]] if f[0] in ja else 'NA'))) for f in (ja.keys() if fields==["*"] else fields)) if cbf: cbf(*args) else: if index: print(index,end='\t') print('\t'.join(args)) if cbf: cbm.finish()
