מסמכי פנמה הם כינוי להדלפת ענק של מסמכי משרד עורכי דין פנמי שמתעסק כנראה בעיקר בהקמת חברות קש במקלטי מס.
הכנראה מצביע על זה שאין לי כוונה לטעון בנחרצות דברים לגבי אף אחת מהישויות שיצוצו בקבצים. אם כבר נאמר משהו – הכל יהיה על פי מקורות זרים.
כוונת הפוסט היא רק לספק קרקע נוחה ומעניינת למשחק hands on עם טכנולוגיית הGraphDB ואין בסיס נתונים מעניין יותר מאשר מסמכי פנמה לצורך העניין.
(ויקי אנגלית, ויקי עברית, האתר עצמו: Offshore Leaks Database )
הנתונים עצמם נמצאים כאן:
וניתנים להורדה בשתי צורות: CSV או DB מוכן של Neo4J בשני המקרים שמתי את הלינק לקובץ הטורנט.
הצעד הראשון הוא הורדה של הDB עצמו מכאן.
לאחר הורדה התקנה והרצה (next next)
יפתח לינק לBrowser מגניב מעל הDB הלוקאלי בכתובת: http://localhost:7474/browser
בכניסה הראשונה צריך להתחבר לשרת עם הסיסמא הדיפולטית, להגדיר חדשה ואז אתם בפנים.

Learn about Neo4J נוגע קצת במונחים והJump into code מאפשר צלילה מאוד נוחה ליצירת DB סרטים ואז תיחקור שלו.
התחקור מתבצע בשפת Cypher שהיא חלק גדול מהיופי בכל העניין.
בהחלט ראוי לאזכר כאן את היפותזת ספיר-וולף שהשפה משפיעה על אופני החשיבה. גם אם אפשר לתחקר הכל בSQL, או בשפת תכנות הרי ששפת התחקור ללא ספק הופכת שאלות רבות לנגישות יותר לשאלה.
MATCH (actor:Person)-[:ACTED_IN]->(movie:Movie)
WHERE movie.title STARTS WITH "T"
RETURN movie.title AS title, collect(actor.name) AS cast
ORDER BY title ASC LIMIT 10;
השפה עצמה מאוד מזכירה SQL עם קצת לוגיקה של RegEx
השאילתא הבסיסית כפי שהיא מופיעה למעלה כוללת:
MATCH – חלק שבו נתאר תבנית שלפיה נפלטר דאטה שתואמת לה. (או מספר תבניות מופרדות בפסיק)
MATCH (_ALIAS_TO_BE_USED_LATER_IN_THE QUERY_:_NODE_TYPE_)-[:_RELATION_TYPE_]->(movie:Movie)
WHERE – סטנדרטי כמו בSQL. (שימו לב לשימוש בmovie הalias שהוגדר בMATCH)
RETURN – אחרי שהגדרנו ופילטרנו אפשר להגדיר מה נרצה להחזיר. שימו לב שיש כאן בעצם implicit group by על פי השדות המוחזרים ושאינם aggregated (במקרה שלנו movie.title)
והפונקציה collect אוגדת לערך אחד מספר ערכים.
…
שיחקתם עם הMovie DB => בואו נעבור הלאה.
עכשיו הזמן להוריד ולהשתמש ב DB של מסמכי פנמה שהורדתם. ( לינק )
סדר הפעולות הוא:
1. stop
2. choose the "panama-papers-windows\neo4j.data\panama.graphdb" directory
3. start
כדי לוודא שהכל עבד בוא נריץ את הquery :
MATCH (a)
where
a.countries = 'Israel'
RETURN labels(a) , count(*)
ואנחנו אמורים לקבל:
count(*) |
labels(a) |
1094 |
[Officer] |
663 |
[Entity] |
865 |
[Address] |
146 |
[Intermediary] |
ועכשיו אנחנו בתוך הDB של מסמכי פנמה, מוכנים לקצת Forensic accounting.
הquery הראשון שנריץ יהיה:
MATCH (a)-[*1..1]-(b)
where
labels(a) <> 'Address'
and a.countries = 'Israel'
RETURN a.node_id,labels(a),a.name,count(*) as cnt
ORDER BY cnt desc
limit 10
ונקבל:
a.node_id |
labels(a) |
a.name |
cnt |
11013202 |
[Intermediary] |
OFIR TSHORNY, ADV (CPA) |
215 |
10165699 |
[Entity] |
ParagonEX Limited |
80 |
11003993 |
[Intermediary] |
MORDECHAI KUPERSCHMIDT, ADVOCATE |
49 |
11006928 |
[Intermediary] |
MOSSACK FONSECA & CO. (ISRAEL) LIMITED |
24 |
11009424 |
[Intermediary] |
BANK HAPOALIM SWITZERLAND |
23 |
12223915 |
[Officer] |
SEMION BUKHMAN |
17 |
10097850 |
[Entity] |
G.S.S. Group Ltd. |
16 |
21957 |
[Officer] |
Tal Hackmey |
15 |
11004430 |
[Intermediary] |
LAURENCE WIZEL FAMILY OFFICE |
15 |
כל הישויות האלו מופיעות במסמכים.
ואפשר להתחיל לצלול ולראות איך נראה מה שנחשף.
נתמקד לדוגמא בישות השניה
השאילתא הבאה מגדירה תבנית של קשר אחד (a מקושר לb)
מגדירה את a כישות מסויימת ( node_id:10165699 ) ובעצם מחזירה את כל הקשרים שלו.
אחד הדברים שמאוד מקל על הבנת התוצאות זה הviewer שמציג גרפים ומאפשר גם לטייל בהם.
(מצד שני עבודה יותר משמעותית איתו מסבירה את הגדולה בממשק של פלנטיר)
MATCH (a)-[*1..1]-(b)
where
a.node_id = "10165699"
RETURN a,b

מה שבעצם רואים כאן
זה ישות מרכזית אחת: ParagonEX Limited
עם כמה עשרות קשרים לישויות מסוג Officer שמוגדרות כ SHAREHOLDER ששימשו (אני מניח) לחלוקת אופציות בחלקן. (שמות כגון: ESOP for X)
חלק מהשמות צפו מאז הפרסום בעיתונות : ( לדוגמא כאן )
רוצים לדעת עוד?
תורידו ותשתעשעו
it's that simple