Partiernas kön

I november förra året undersökte SCB i sin partisympatiundersökning hur fördelningen mellan män och kvinnor såg ut bland de som kunde tänka sig att rösta på ett visst parti i nästa val. Resultatet blev följande:

scb

Vad som kanske överraskade lite var den stora övervikten av män bland Sverigedemokraterna. Den var så stor att den fick alla andra partier att bli (svagt) kvinnodominerade. Sådan blir ju effekten av att ha riksdagsvalet som modell för vad som ”gör” ett parti. Allt kommer i slutändan bli 100 procent.

Finns det ett annat sätt att belysa kön på? En opinionsundersökning i linje med SCBs undersökning siktar ju bara på valresultatet som ett slag facit och ger ett extensivt mått. Men hur ser det ut när det politiska diskuteras? Ett sätt att studera det offentliga samtalet är att se vad som sägs på Facebook. På så sätt får man en mera processuell och rörelsebaserad indikation på hur det politiska byggs från handling till handling i offentligheterna. Vilka är det som dominerar i detta samtal?

För att undersöka detta laddade jag ned ett stort antal poster på de olika partiernas Facebooksidor (från 400 till 1000 poster, exklusive Kd som inte har något officiell sida) och gick igenom de ca. 100 000 namn som förekommer i kommentarstrådarna. Facebook håller förvisso ganska bra koll på vilket kön varje användare har, men denna information är inte öppet tillgänglig för övervakning via Graph-APIet som man använder för att skrapa data.

Så då fick jag lösa det med ett litet hack.

Jag körde alla hundratusen namn genom mitt lilla program gendercounter (som även utgör motorn i Genuskollen.se) och räknade hur ofta manliga och kvinnliga namn förekom (i absoluta tal, dvs. samma unika namn kan förekomma flera gånger). Resultatet blev så här:

resultat

När det kommer till kommentarer på Facebook är männen ständigt överrepresenterade, med undantag för Feministiskt initiativ som är det enda parti som har fler kommenterande kvinnor än män. Den generella trenden är att högerut är det fler män och vänsterut fler kvinnor. Men Sd sticker i denna undersökning inte ut mer än något annat högerparti. Istället är det Moderaterna som har flest män som kommenterar på sin Facebooksida.

Så här ser datamängden ut i tabellform för frekvens av namn (procenttalen avrundade, därför kan det bli 101% när man summerar):

Parti Kvinnor Män Obestämd N
Kommentarstrådar
Fi 55 32 13 10345 853
V 38 48 14 19429 998
S 37 48 15 20174 1004
Mp 34 53 13 15101 965
C 24 66 10 7512 732
L 27 65 9 10404 725
M 22 70 8 22354 1002
Sd 25 64 11 10529 427

Nu finns det flera metodproblem som jag ännu inte har löst, så dessa resultat ska läsas med försiktighet. Det som sorteras som ”obestämt” är  namn som inte förekommer i listorna som matchar namn. Det kan exempelvis röra sig om olika ”smeknamn”, men det kan även om genusneutrala namn. Jag jobbar kontinuerligt med att öka denna träffsäkerhet, men först måste man utsätta sig för riktig data innan man hittar anomalierna.

Trenden är ändå ganska tydlig. Kanske kastar denna typ av undersökningar nytt ljus på de politiska samtalens förutsättningar. Det verkar i så fall som att nästan alla Facebooktrådar är sorgligt mansdominerade.

\\

Metod / Kod

Först skrapade jag varje partis Facebooksida med följande skript. Fyll i sidornas ID-nummer och din access_token:

from facepy import GraphAPI
from django.core.serializers.json import DjangoJSONEncoder
import json

group_id =""
access_token = ""

graph = GraphAPI(access_token)
pages = graph.get(group_id + "/feed", page=True, retry=3, limit=1) #This is the number of posts per file!! original value 1
i = 0
for p in pages:
    print('Downloading page', i)
    with open('Partinamn/%scontent%i.json' % (group_id, i), 'w') as outfile:
        json.dump(p, outfile, indent = 4, cls=DjangoJSONEncoder, ensure_ascii=False)
    i += 1

Jag stoppade skriptet när det översteg 1000 poster för att inte översköljas av data.

Därefter körde jag följande skript för att räkna namn. Observera att jag importerar gendercounter som en modul, vilket gör att man först måste avkommentera några rader som sköter filöppning etc (se kodkommentarerna) samt lägga både gendercounter och dess namnlistor i samma katalog.

#-*- coding: utf8 -*-
import json
from json import load
from os import listdir
import gendercounter

counter = 0
kvinnocounter = 0
maencounter = 0
undetermined = 0
commentfield = 0

recordlist = []

directory = "Partinamn/"


#### Multi file parser from directory
for filename in listdir(directory):
    with open(directory + filename) as currentFile:
        jsondata = load(currentFile)

    for item in jsondata['data']:
        #print(item['status_type']) #For debugging
        if item:
            try:
                if item['comments']['data']:
                    commentfield += 1
                    print("Begin new post.")
                    for i in item['comments']['data']:
                        print("-" * 20)
                        namefield = i['from']['name']
                        splitted = namefield.split()
                        firstname = splitted[0]
                        print(firstname)
                        resultat = gendercounter.textinput(firstname)

                        if resultat[0][0]:
                            print("Kvinnonamn " + str(resultat[0][0]))
                            kvinnocounter += 1
                        elif resultat[1][0]:
                            print("Mansnamn " + str(resultat[1][0]))
                            maencounter += 1
                        else:
                            print("Couldn't determine gender")
                            undetermined += 1

            except KeyError:
                print("there was a key error")
            print("\n")


print("Results for the dicretory: " + directory)
print("There number of comment threads: " + str(commentfield))

summa = kvinnocounter + maencounter + undetermined
print("Summa namn: " + str(summa))

print("Kvinnocounter: " + str(kvinnocounter))
print("Maencounter: " + str(maencounter))
print("Undetermined: " + str(undetermined))

print("Kvinnor, " + str(kvinnocounter / summa))
print("Män, " + str(maencounter / summa))
print("Icke-bestämda, " + str(undetermined / summa))

 

Monadologiska undersökningar 3: Visualisera kommentarsfält på Facebook

faschmap

Jag blev lite knäpp av att bara göra något halvgjort i förra inlägget. Så här kommer någon form av fortsättning, dels ett lite mera aggressivt inhämtningsskript och dels ett sätt att skapa nätverksfiler av datan som man får ned från facebook.

Först testade jag att hämta ned så mycket jag kunde från ett gäng nyfascistiska Facebooksidor. Mest för att se om det fanns kopplingar på monad/divid-nivå. Jag uppgraderade det förra skriptet att iterera över en dictionary och spara i en ny katalog med passande filnamn:

from facepy import GraphAPI
from django.core.serializers.json import DjangoJSONEncoder
import json
import time
import os

fascistfeeds = {"Sverigedemokraterna": 676246449160270,
                "Avpixlat": 1456773041274824,
                "SvP": 277195872311475,
                "Sdkvinnor": 169003303168526,
                "Ungsvenskarna": 1491422081182615,
                "Sdkuriren": 665250476818577,
                "Samtiden": 256690774389618,
                "Folkomrostningen": 1710097892544837,
                "Giveemhell": 1075216222492967,
                "Kabbelsvetsarn": 742925315824067,
                "Armanrasist": 146597985381739
                }

#Create a directory with today's date.
print("Today's date is:" + time.strftime("%Y%m%d"))
todaydate = time.strftime("%Y%m%d")

if not os.path.exists("scrape" + todaydate):
    dirdatename = "scrape" + todaydate
    os.makedirs(dirdatename)
else:
    print("Directory already exists, exiting.")
    quit()


for key, value in fascistfeeds.items():
    print(key, value)

    group_id = "%s" % value
    access_token = "Put here the token from https://developers.facebook.com/tools/explorer/"
    graph = GraphAPI(access_token)
    pages = graph.get(group_id + "/feed", page=True, retry=3, limit=1) #This is the number of posts per file!! original value 1
    i = 0
    for p in pages:
        print('Downloading page', key, i)
        with open('%s/%scontent%i.json' % (dirdatename, key, i), 'w') as outfile:
            json.dump(p, outfile, indent = 4, cls=DjangoJSONEncoder, ensure_ascii=False)
        i += 1

Urvalet är pseudo-slumpmässigt. Jag klickade bara runt lite i den bruna sörjan för att få mera data. När jag körde skriptet ovan fick jag hem 7858 postningar som sparas i varsin fil, sammanlagt 168 Mb data.

Redan här har man en datamängd som man kan jobba rätt bra med. Man kan söka efter ord och användare. Troligtvis finns det intressanta saker man kan göra med alla kommentarers fulltext, deras språkbruk, vem som säger vad etc. Men det är en annan form av analys.

Jag är intresserad av hur vanligt det är att en person kommenterar på en post på Sverigedemokraternas sida och sedan går över till Avpixlat och gör det samma, och så vidare längs hela datamängden. Då får vi fram en relation mellan dessa två aktörer som är medierad av en divid. Sverigedemokraterna och Avpixlat kan närma sig varandra till exempeln när en en Sd-politiker skriver på nyhetssidan. Men ett närmande kan också ske ”underifrån” i och med att en aktör-divid kommenterar på båda sidorna, ett närmande som är minst lika viktigt för att skapa associationer. Att den ena aktören är en politiker och den andra en ”helt vanlig människa” är inte nödvändigtvis en gradskillnad, utan snarare en slags modulation av en liknande relation. Attraktion är en kraft för mikrofascismen.

Nog med teori! För att vaska fram de aktörer som kommenterat på sidorna som nedskrapats från Facebook, skrev jag det här krytpiska skriptet:

from gexf import *
from json import load
from os import listdir
import hmac
import hashlib


gexf = Gexf("Facebook interactions", "Comments to Page")
graph = gexf.addGraph("directed", "static", "Facebook directed network")

edgelist = []

#### Multi file parser from directory
for filename in listdir("scrape20151128/"): #change path here (1/2)
    with open("scrape20151128/" + filename) as currentFile: #change path here (2/2)
        jsondata = load(currentFile) #parse json.

    ###The hash function. Note that the hashlib function needs to
    ###be inside the loop to preserve data integrity.
    for item in jsondata['data']:
        #print(item['from']['name'])
        targetgroup = item['from']['name']

        #This loop extracts comments. make sure to separate "i" and "item"
        #Change whatever you want to print.
        try:
            if item['comments']['data']:

                for i in item['comments']['data']:

                    digest_maker = hmac.new(b'rep7ac3withs0p3recretk3y', i['from']['id'].encode(), hashlib.sha256)
                    #print("Encrypted id: " + digest_maker.hexdigest()) #for debugging
                    hasheduser = digest_maker.hexdigest()
                    user = i['from']['id'] + i['from']['name'] #Plaintext user, for debugging only.
                    #print(hasheduser + targetgroup)
                    #strhasheduser = hasheduser.decode(encoding='UTF-8')
                    graph.addNode(hasheduser, hasheduser)
                    graph.addNode(targetgroup, targetgroup)
                    edgelist.append( (hasheduser, targetgroup) )

        except KeyError:
            break

#print(edgelist) #for debugging

for k, v in enumerate(edgelist):
    print(k, v[0], v[1])
    graph.addEdge(k, v[0], v[1])
    #print(k, v)

output_file=open("fascistfeeds.gexf","wb")
gexf.write(output_file)

Om allt går som det ska så spottar skriptet sedan ur sig:
Facebook directed network directed static
number of nodes : 13138
number of edges : 73721

Den .gexf-fil som sedan genereras kan öppnas med Gephi. Det blir lite kärvt med minne och processor vid så här stora datamängder, men det gick på min laptop.

På bilden ovan (ursäkta unicode-haveriet, någonstans i Gephi gick det fel) ser vi alltså facebook-sidorna som de stora noderna. Varje gång en divid kommenterar på en sida, skapas en relation, en så kallad ”edge”. Varje divid kan kommentera på flera olika sidor (de hashade facebook-idnumrena håller reda på dem utan att avslöja identiteten) vilket gör att sidorna hamnar lite närmare varandra.

Det här var återigen bara ett test. Inga slutsatser att går att dra av resultatet. Men däremot borde det gå att fundera på vad som kan göras rent metodologiskt.

Monadologiska undersökningar 2 – Överlappande facebooksidor

Jag snubblade över en liten idé (eller så snubblade den på mig) när jag satt och kodade på en anonymiseringsteknik för facebookdata. Det konventionella sättet att se på politiska ideologier är ju att de formas och formuleras ”uppifrån”, att de har en normkälla och är underblåsta av en kraftig bas som skapar dess centraliserande kraft kring ett Budskap (som forskaren tolkar och säger Sanningen om till de som inte vet bättre).

Ett annat sätt att se på saken är att börja ”nedifrån och upp”, alltså i det sorlande hav av monader, divider, aktanter (vad vi kallar dem spelar inte särskilt stor roll). Här blir det intressant att studera de politiska varelsernas rörelser, eftersom det är dessa mönster och interaktioner, dessa översättningar och allianser, som i sin tur konstituerar det som vi ser som en politisk helhet. Här talar man mindre om de totalitära idéerna som texter och teser, utan letar efter totalitära affekter, begär, existensformer, interaktionsformer etc. Här hittar man inte fascismen, utan mikrofascismen.

Den empiriska data som presenteras nedan är bara ett litet test och det går inte att dra några slutsatser av dem. Själva insamlingen gjordes medelst det lilla pythonbiblioteket facepy. Jag gick till de öppna sidorna för Sverigedemokraterna, Miljöpartiet, Svenskarnas parti och Avpixlat och laddade ned så mycket jag kunde med Facebooks API-nyckel. Inga speciella tankar om urval alltså, jag hämtade bara vad jag fick, vilket varierade från några hundra till några tusen poster. Därefter valde jag ut alla kommentarer på alla poster och förvandlade varje användares unika Facebook-id till en kryptografisk hashsumma (för anonymisering). Dessa extraherades och skrevs till nya filer som sedan jämfördes i en korstabell:

Sd Mp Svp Avpixlat
Sd 80 92 47
Mp 80 22 3
Svp 92 22 5
Avpixlat 47 3 5

Vad säger då denna figur? Den visar på samförekomst (co-occurrence) av (hashade) Facebook-id mellan Facebooksidorna. Det finns alltså 80 tillfällen då samma person har kommenterat på både Miljöpartiet och Sverigedemokraternas sida, 92 gånger på Sd och Svenskanas Partis sidor, osv. Vi följer alltså konkreta personer, men har avidentifierat dem (visst skulle detta vara en läskig form av ”åsiktsregistrering”).

Men det känns ju väldigt kontraintuitivt att det skulle vara större samförekomst mellan Sd och Mp än vad det skulle vara mellan Sd och Avpixlat. Sd och Svp ligger förvisso nära varandra ”ideologiskt”, men å andra sidan konkurrerar de om om röster. Som ni märker förklarar den aggregerade nivån väldigt lite. Men den kan ändå ge oss vissa riktningar att gå i, vissa spår att följa.

Vad är det då som förklarar siffrorna? Svaret är att informationsrikedomen ökar med förstoringen. Vi måste alltså dyka ned i de 80 samförekomsterna (i ett datamaterial av tiotusentals interaktioner) för att se vad Miljöpartister och Sverigedemokrater har gemensamt (inom ramen för mitt slarvigt genomförda testurval). Men om vi gör det så bryter vi anonymiteten!

Nu kan man förvisso tänka att det är oproblematiskt att ändå analysera detaljerna i helt öppna Facebooksidor och därmed tumma på anonymiteten, eftersom de är tillgängliga för vem som helst på internet.

En viktig sak är nämligen att varje enskilt fall av samförekomst kan ha diametralt olika anledningar till varför den uppstod. Jag hittar exempelvis en miljöpartist som gillar djur som har kommenterat på Sverigedemokraternas sida med:

”Något Sd borde fundera över? Man måste inte alltid tycka som storebror?”

Å andra sidan kommenterar en Sverigedemokrat så här på Miljopartiets sida:

TBC-fall ökar och ökningen härrör uteslutande från personer som kommer hit utifrån. Vad gör ni konkret för att säkerställa att inte diverse smittsamma sjukdomar sprids (dvs det handlar om upprätthållande av folkhälsan)? Vilka resurser tillför ni nu skolor, sjukvård, sociala myndigheter,polis, säkerhetspolis, skolor, kommuner när belastningen på dem ökar kraftigt?

Två exempel av 80 möjliga, totalt icke-representativa. Poängen med detta är bara att göra en distiktion mellan det molekylära och det molära. Hade vi genomfört en opinionsundersökning hade vi fått en jämförelse av folks åsikter utefter kategoriella frågor; vad anser du om X, Y, Z? Resultat: ett genomsnitt.

Men med denna approach, å andra sidan, får vi istället ett ”omvänt arbete”. Varje monad som interagerar med andra monader definierar själva frågan som ställs av dem, men inte utifrån en given kategori, utan snarare utefter imitation/repetition.

Vad som är målet är alltså att kvantifiera dessa kvalitéer så att man dels kan se aggregatens struktur utan att tumma på monadernas myller. Men detta sker nu  utan abstraktioner och ”abstrakt tänkande”. Istället når vi framkomlighet genom repetitioner och associativt tänkande. Lättare sagt än gjort.

Vad tror ni? Förslag på saker som skulle vara intressanta att titta närmare på?

\\

Några skriptsnuttar jag använt mig av.

För att kryptera de enskilda användarnas id-nummer i kommentarsfältena:

from json import load
from os import listdir
import hmac
import hashlib


#### Multi file parser from directory
for filename in listdir("miljopartiet/"): #change path here (1/2)
    with open("miljopartiet/" + filename) as currentFile: #change path here (2/2)
        jsondata = load(currentFile) #parse json.

        #This loop extracts comments. make sure to separate "i" and "item"
        #and hashes them
        try:
            if item['comments']['data']:
                for i in item['comments']['data']:
                    digest_maker = hmac.new(b'r3placewithmegasecretk3y', i['from']['id'].encode(), hashlib.sha256)
                    print(digest_maker.hexdigest())
        except KeyError:
            break

För att räkna fram co-occurrences är det bara att jämför hashsummorna som extraherats ovan, fil för fil. Ungefär:

with open('mpencrypted.txt', 'r') as file1:
    with open('sdencryptedt.txt', 'r') as file2:
        same = set(file1).intersection(file2)

same.discard('\n')

print(same)
print("Number of co-occurences: ")
print(len(same))

Anonymisera facebookdata för forskning med hmac och hashlib

Om man vill samla in data från Facebook i forskningssyfte stöter man genast på forskningsetiska problem. Facebook ger alldeles för mycket information om informanterna, utan att man ens behöver be om lov.

Här tänkte jag bara ta upp en detalj som handlar om den ”farligaste” uppgiften i den datamängd som man kan extrahera med Facebooks API: det unika id-numret.

Varje Facebookanvändare har ett femtonsiffrigt nummer tatuerat i sitt digitala skinn. Det ser ut så här (i (förkortat) json-format):

    {
     "id": "48236456782311475_63332119186437",
     "message": "This is a message written by an informant",
     "type": "status",
     "from": {
         "id": "121506454323368",
         "name": "Jane Doe"
     },
     "created_time": "2011-06-11T25:48:31+0000",
     "status_type": "wall_post",
     "is_expired": false
    }

De två fält som är uppenbart identifierande är alltså id och name. Här tänkte jag bara ta upp id-numret. Att ersätta namnet men behålla man/kvinna-distinktionen är ett problem som måste lösas på ett annat sätt.

För att kunna bevara det unika med id-numret utan att kunna identifiera en riktig person tänkte jag att man skulle kunna använda kryptering. Men jag är inte så duktig på det så jag undrar nu om detta kan vara ett vettigt angreppssätt.

Eftersom id-numrena alltid är femtonsiffriga så är det nämligen möjligt att räkna fram alla hashsummor, även om det skulle ta lite tid. Men om man däremot använder HMAC så lägger man till ett lager av säkerhet genom att man använder en unik hemlig nyckel och krypterar med. Så här tänkte jag ungefär:

from json import load
from os import listdir
import hmac
import hashlib

#Some code for reading files and parsing the data to jsondata

    for item in jsondata['data']:
        print("-" * 20)
        print("Name: " + item['from']['name'])
        print("Facebook id: " + item['from']['id'])
        digest_maker = hmac.new(b'replacewithsuperecretk3y', item['from']['id'].encode(), hashlib.sha256)
        print("Encrypted id: " + digest_maker.hexdigest())

Detta skriver ut:

Name: Jane Doe
Facebook id: 121506454323368
Encrypted id: dfef8d5bed530668b004e28a29488e8252e5a5224d3178f00c0f7d0bf48e4b6a

Detta gör att man kan bygga om forskningsdatan och ersätta id-numret med det krypterade numret.

Nu finns det tusen andra saker i materialet som kan avslöja en användares identitet. Men, bortsett från detta, tror ni att den här krypteringsmetoden är tillräckligt bra?

Om övervakning 2

bildt

Jag tror inte att det är en bra idé att utöka övervakningen precis här och nu. Man måste se bortom både fruktansvärda dåd  och misslyckade polisinsatser. Istället bör man titta bakåt och framåt längre än den politiska opinionen kan nå för tillfället. Här kommer några hållpunkter som kan vara bra att ladda in i det tänkande arbetsminnet, så att impulserna inte får enväldig makt över argumentationen.

För det första: datalagringsdirektivet. Eftersom detta förklarats ogiltigt av EU-domstolen så skulle man kunna tänka sig att det hänger löst även i Sverige. Men jag tror att det sitter ganska säkert. Dels misstänker jag att det inte kommer finnas någon som helst opinion för att riva i den svenska implementeringen (ingen politiker skulle våga). Men under ytan finns en viktigare aspekt.

Som avslöjades i ett SVT-reportage för två år sedan har man i princip automatiserat SÄPOs tillgång till datalagrade uppgifter. Det behövs alltså inga juridiska kontrollmekanismer för att data ska lämnas över, bara några knapptryckningar. När reportaget skrevs hade systemet bara införts delvis. Hur det funkar idag vet jag inte (länktips mottages gärna!). Men när ett system redan permanenterats som ett verktyg är det nog svårt att nedmontera det, även om det skulle vara ogiltigt på EU-nivå.

För det andra: frågan om ”statstrojaner”. Här råder det ju en förvirring eftersom många verkar tro att det handlar om att polisen ska få tillgång till exempelvis Skype. Men så är knappast fallet, tillgång till denna typer av tjänster får de redan som det är. När det kommer till de (i huvudsak amerikanska) nätjättarna så har man upparbetat rutiner för att snabbt få tillgång till informationen, som ju såklart är krypterad.

Med trojaner menas något annat. Det innebär att i de flesta fall att man köper mjukvara från ett skumt företag som Hacking Team, Finfisher eller Bluecoat (som Telecomix avslöjade), företag som inte har några skrupler att sälja samma produkter till vidriga diktaturer. Dessa mjukvaror kapar sedan den misstänktes dator eller telefon, på lite olika sätt beroende av hur bra produkten är. Man kan även tänka sig att man utvecklar en egen lösning, men det har troligtvis inte SÄPO resurser att göra. Fördelen med dessa är att de kräver någon form av eftertanke innan de används. De skalar inte upp på det sätt som datalagringen gör (fritt fram att extrahera hur mycket data som helst), utan man måste koncentrera sig till misstänkta individer. Däremot är dessa system ganska osäkra. När det började läcka om de företag (se bland annat Wikileaks Spyfiles och Hacking Teams läckta e-post) som sålde trojanska hästar så framkom det hur taffliga deras produkter var. Det innebär alltså en säkerhetsrisk bara att använda dem. Dels är går de att upptäcka, vilket genast gör den misstänkte medveten om att hen är övervakad. Dels öppnar man upp en IT-säkerhetslucka mot sig själv, eftersom programvaran ju ”ringer hem”.

Det är viktigt att både SÄPO och FRA har precis rätt verktyg och befogenheter som krävs för att försvara det öppna samhället utan att för den sakens skull upplösa det. Det är en mycket svår balansgång som man inte ska försöka vandra om det blåser kraftiga vindar.

Om övervakning

Jag skriver inte så ofta om övervakning längre, men i kölvattnet av den senaste tidens terrordåd skrev jag ändå en debattartikel i Expressen. Egentligen manar jag mest till eftertanke snarare än handlingskraft. Det är inte så genomtänkt att stifta övervakningslagar direkt efter ett dåd, något som historien visar.

När det kommer till diskussionen kring huruvida polisen ska få hacka sig in i folks datorer, vad man på tyska så vackert kallar för Staatstrojaner, så har jag blandade känslor. När denna typ av övervakning används av president Mubarak framkallas genast bilden av en mycket totalitär form av övervakning. Samtidigt utgör detta tillvägagångssätt en mycket riktad form av övervakning, alltså, motsatsen till ”massövervakning”. Vad säger ni?

Spionen i fickan

Den 13 oktober föreläser jag om ”Spionen i fickan” på Näckrostimmen.

Utöver vad som står i beskrivningen tänkte jag göra en utvikning som tangerar vad som händer i korsningen mellan ”övervakning” och ”skuldsättning”, med inspiration från Kina.

Klarna Faktura påverkar oss nog mer än både FRA och NSA sammanlagt (hypotes).

TID: 18.00-19.00
PLATS: Humanistiska biblioteket, Renströmsgatan 4 (Göteborg)
Fri entré

Monadologiska undersökningar – Hyphe + Gephi + Sigma.js

Zooma genom att skrolla. Klicka för att aktualisera varje enskild monads nätverk. Se även fullskärmsversion
I mellandagarna har jag experimenterat med några verktyg för datalandskapsforskning/journalistik/aktivism. Detta i syfte att analysera världen med en monadologisk ontologi utifrån Gabriel de Tarde. Här tänkte jag dela med mig av några metodologiska/mjukvarumässiga knep som jag har lärt mig (autodidaktiskt) över många koppar svart te.

För att kunna se datalandskapet för vad det är, måste vi använda oss av några instrument som förstärker och förtydligar den snåriga djungel som uppstår i datamatrisens bördiga jord. Här vandrar en mängd muterade arter och avarter omkring. Men primärt är vi inte intresserade av deras ”essens”, utan istället deras performativitet. Varje nod definieras av sitt nätverk samtidigt som nätverket definierar noderna.

Tack vare internet lämnar nästan alla aktiviteter efter sig digitala spår. Genom att skicka ut spindlar (crawlers) går det att sniffa upp dessa spår och sedan analysera dem. Datalandskapet är fyllt av sådana spår och tack vare att vi lämnar dem efter oss är det enkelt att bevaka och övervaka nätet.

Vi är alla flugor i arachnidernas fiberoptiska fångstapparat.

\\

Médialab vid Sciences Po tillhandahåller ett antal open-sourcade verktyg som utgår från en monadologisk ansats. För att samla in data måste en ha en vettig crawler som kan skrapa och indexera den information en vill åt. Hyphe (github) är en mycket lättanvänd sådan, som tyvärr ännu är i ett tidigt utvecklingsstadium och därför inte helt enkelt att installera 1.

Hyphe tillåter att man genomför en slags ”snöbollscrawling”. I exemplet ovan utgick jag från en populär hemsida bland svenska män, vilket gav följande resultat:

Skärmavbild 2015-01-05 kl. 09.26.56

När man väl har angett en startpunkt, hämtar sedan Hyphe fram de relevanta länkarna till andra noder i nätverket:

Skärmavbild 2015-01-05 kl. 09.31.55

Hyphe sätter sedan igång att crawla alla noder en väljer att inkludera i nätverket. Allt som allt skapade jag detta nätverk på cirka tio minuter, bara för att testa. Men har en mera tid kan en dels bygga ett större nätverk, och dels sortera och klassificera noderna så att en får en tydligare visualisering.

Hela tiden skapar hyphe automatiskt förhandsgranskningar av det nätverk man bygger ihop:

Skärmavbild 2015-01-05 kl. 09.33.52

Sedan är det enklast att exportera resultatet till .gephx-formatet och sedan fortsätta bearbetningen i Gephi.

För att sedan publicera en interaktiv visualisering kan man dels installera ett plugin som exporterar Gephi-nätverk till sigma.js eller installera sigma.js-biblioteket på en webserver och direkt låta det läsa in gephx-filen (om man inte orkar Gephi).

Då blir det lite enklare och roligare att visa upp visualiseringen utan att skapa en massa statiska bilder.

\\

Att kravla och skrapa webben ger givetvis en begränsad mängd data som är av en viss typ. Noderna utgörs av ”web-entiteter” och en web-entitet består sedan av ytterligare nätverk. Tänk <a href=”http://www.expressen.se/nyheter/expressen-avslojar/namn-pa-anonyma-anvandare-knackta/”>alla de som kommenterar på bloggarna och hemsidorna</a> i nätverket! Men för att komma åt den nivån måste en utvidga med att <a href=”http://www.christopherkullenberg.se/monader-sociala-natverk-och-facebookovervakning/”>skrapa exempelvis sociala medier</a>.

Imitationer.

Noder som imiterar andra noder.

Näthatet uppstår

i nätverken.

Notes:

  1. Jag lyckades med att få igång Hyphe på en Debianserver (Debian 7). Dock är installationsskriptet aningen trasigt och måste läsas igenom manuellt för att tillgodose alla dependencies. En måste även lägga till GPG-nycklar manuellt och sedan lyckas klura ut hur Apache2 gör Alias-pekningar. Jag rekommenderar även starkt att en prövar först på en virtuell maskin eller på en maskin som man inte använder till något annat, detta eftersom installationen av scrapy-motorn kommer att ersätta sysvinit, vilket är ganska så risky business. Hör gärna av er till mig om ni kör fast.

Monader, slem och issuecrawler

slem

Som ett test skrapade jag några bloggar för analys av länkrelationer. Testet bestod mest av att se vilken typ av data som Issuecrawler kunde generera. Issuecrawler används bland annat av MappingControversies, som i sin tur använder sig mycket av Latour, Tarde och Dewey som teoretisk grund. Det verkar användbart även om jag inte har lyckats förstå exakt hur djupt Issuecrawlers motor går ned länkarna. Om någon vill testa, kolla källdatan i Gephi-format.

Jfr. även ”slemmappning

Monader, sociala nätverk och facebookövervakning

whole communityShip to Gaza Network

Jag har funderat lite vidare på det där med aktörsnätverk och monader och kände att det var på sin plats att testa några fler empiriska ingångar. Medelst ett pseudonymt spionkonto på Facebook började jag samla data.

\\

I samtidslaveriets tyckonomi skapas det hela tiden ett överflöd av ”åsikter” i sociala medier. Dessa är för det mesta ganska ointressanta på en innehållsnivå. Vad man kanske däremot inte tänker på är att varje litet klick på aggressiva/invasiva nättjänster som Facebook kommer att lagras, sorteras och användas för att zooma in på monadiska mönster som eventuellt går att omsätta till konsumtionsbeteende och annat matnyttigt. Det är inte konstigt att Facebook och Mastercard samkör sina datamängder. Ibland kallar vi detta för nätets kontrarevolution.

\\

Med hjälp av Gephi och NodeXL började jag skrapa ned Ship to Gaza Swedens facebooksida för att visualisera vad som gjordes där. Det går med vilken facebooksida som helst, det är mest att det är lite roligt att visualisera en ”aktivistsida” så att man kan betrakta eventuella känslor av paranoia på ett intressant sätt.

Jag tog bara ned data för en månad som ett litet test, men det blir ändå väldigt många relationer i databasen. Zoomar man in i mitten hittar man den mest centrala noden, som föga förvånande utgörs av administratören för sidan.

Om man öppnar upp hela denna monad som på bilden bara är förkortad till ”Ship…” (jag förkortar varje nod så att det inte står fulla namn i datamängden, lite ”integritet” kan ju vara lämpligt), får man följande händelse:

Ship to Gaza-Sweden: Anonym Anonymsson, har du någonsin belägg för vad du skriver? Vad är det för antisemitiska satirer du pratar om? Vilka medlemmar har uttryckt sig antisemitisk? Ship to Gaza har aldrig, och kommer aldrig uttrycka sitt stöd för Hamas eller någon annan palestinsk fraktion. Vi är politiskt oberoende!

Detta kallar vi under normala omständigheter för en ”debatt”. Dessa ”debatter” liknar kvällstidningarnas ”klick-monster” eller den pressens fåraktiga försvarstal när man som ursäkt för att ha publicerat något rasistiskt eller sexistiskt ”bara ville väcka debatt”. Att väcka debatt leder till klick som leder till cash. Denna centralaste nod i nätverket får massor av klick, likes och kommentarer, och datorns algoritmer använder dessa för att beräkna centralitet (i just detta fall).

Men, det är kanske inte primärt för att analysera klickmonster som man utför sociala nätverksanalyser. Istället vill man kanske kartlägga olika ”sub-communites”, eller ”delgemenskaper” i en större gemenskap. Håll i minnet: helheten är alltid mindre än delarna. Vi zommar in:

 

I hela datamängden räknade Gephi ut (matematiskt) att det fanns 30 undergemenskaper. Här har jag zoomat in i en grönfärgad sådan. De bildar en tillfällig gemenskap genom att de ”likear” varandra eller kommenterar i en tråd. I materialet hittar man även mera aktiva noder, som ofta länkar samman gemenskaper och fungerar som bryggor mellan dem. Ur ett monadperspektiv är det inte så intressant vad du säger, utan snarare ”vem du säger”. Det är på så sätt som delen är invikt i helheten och vice versa.