Python capture Keystrokes values in text file on OS X

跟風遠走 提交于 2019-12-21 02:36:09

问题


I am trying to monitor keystrokes on my Macbook on order to build a statistics analyzer. But how can I isolate the chars from "event" which is more something like :

NSEvent: type=KeyDown loc=(850,248) time=66551.8 flags=0x100 win=0x0 winNum=0 ctxt=0x0 chars="l" unmodchars="l" repeat=0 keyCode=37

So do anyone know how to, based on the script posted below, fulfill a .txt doc with the value of chars (from NSEvent) ? I need a text file with a the pressed keys in order to run my other script on it and analyze the frequency etc...

Thanks in advance ;)

#!/usr/bin/python
# -*- coding: utf-8 -*-


from AppKit import NSApplication, NSApp
from Foundation import NSObject, NSLog
from Cocoa import NSEvent, NSKeyDownMask
from PyObjCTools import AppHelper

class AppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, notification):
        mask = NSKeyDownMask
        NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(mask, handler)

def handler(event):
    try:
        print event
    except KeyboardInterrupt:
        AppHelper.stopEventLoop()

def main():
    app = NSApplication.sharedApplication()
    delegate = AppDelegate.alloc().init()
    NSApp().setDelegate_(delegate)
    AppHelper.runEventLoop()

if __name__ == '__main__':
    main()

回答1:


#!/usr/bin/python2.6

#  You _must_ turn on assistive devices under Accessibility prefpane 
# for any of this code to work. Otherwise it won't do anything.

from Cocoa import *
from Foundation import *
from PyObjCTools import AppHelper
import keycode
import string
import sys

class AppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, aNotification):
        NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSKeyDownMask, handler)

def handler(event):
    if event.type() == NSKeyDown and keycode.tostring(event.keyCode()) in string.printable:
        print keycode.tostring(event.keyCode())

def main():
    app = NSApplication.sharedApplication()
    delegate = AppDelegate.alloc().init()
    NSApp().setDelegate_(delegate)
    AppHelper.runEventLoop()


if __name__ == '__main__':
   main()

I dug around a bit and found github user 'gurgeh's OSX modifications for selfspy in his branch - https://github.com/gurgeh/selfspy/blob/new_activity/sniff_cocoa.py.

I put a few of my own ideas into it and this is the result. Kudos to gurgeh for figuring out how to capture window change events - this makes the key logger much more interesting since you could basically ignore apps that don't provide interesting events, or for the statistically minded, graph out which apps you use the most and what you're doing in them..

#!/usr/bin/python2.6

import exceptions
import sys
from Foundation import NSObject, NSLog
from AppKit import NSApplication, NSApp, NSWorkspace
from Cocoa import *
from Quartz import CGWindowListCopyWindowInfo, kCGWindowListOptionOnScreenOnly, kCGNullWindowID
from PyObjCTools import AppHelper
import keycode

evtypes = dict(
    NSLeftMouseDown     = 1,
    NSLeftMouseUp       = 2,
    NSRightMouseDown    = 3,
    NSRightMouseUp      = 4,
    NSMouseMoved        = 5,
    NSLeftMouseDragged  = 6,
    NSRightMouseDragged = 7,
    NSMouseEntered      = 8,
    NSMouseExited       = 9,
    NSKeyDown           = 10,
    NSKeyUp             = 11,
    NSFlagsChanged      = 12,
    NSAppKitDefined     = 13,
    NSSystemDefined     = 14,
    NSApplicationDefined = 15,
    NSPeriodic          = 16,
    NSCursorUpdate      = 17,
    NSScrollWheel       = 22,
    NSTabletPoint       = 23,
    NSTabletProximity   = 24,
    NSOtherMouseDown    = 25,
    NSOtherMouseUp      = 26,
    NSOtherMouseDragged = 27
)

evtypes_rev = dict([[v,k] for k,v in evtypes.items()])

class Hooker(object):
    def __call__(self, *args, **kwargs):
        try:
            evt = kwargs.get('event')
            del kwargs['event'] 
            items = ' '.join( [ x[0]+"="+unicode(x[1]) for x in kwargs.iteritems()] )
            print "%20s | %22s | %s" % ( self.__class__.__name__, evtypes_rev[evt.type()], items)
        except Exception as e:
            print 'Horrific error!', e
            AppHelper.stopEventLoop()
            sys.exit(0)

class KeyHooker(Hooker): pass
class MouseButtonHooker(Hooker): pass
class MouseMoveHooker(Hooker): pass
class ScreenHooker(Hooker): pass

class SniffCocoa:

    def __init__(self):

        self.key_hook = KeyHooker()
        self.mouse_button_hook = MouseButtonHooker()
        self.mouse_move_hook = MouseMoveHooker()
        self.screen_hook = ScreenHooker()
        self.currentApp = None

    def createAppDelegate (self) :

        sc = self
        class AppDelegate(NSObject):
            def applicationDidFinishLaunching_(self, notification):
                mask = (
                          NSKeyDownMask 
                        | NSKeyUpMask
                        | NSLeftMouseDownMask 
                        | NSLeftMouseUpMask
                        | NSRightMouseDownMask 
                        | NSRightMouseUpMask
                        | NSMouseMovedMask 
                        | NSScrollWheelMask
                       )
                NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(mask, sc.handler)
        return AppDelegate

    def run(self):
        NSApplication.sharedApplication()
        delegate = self.createAppDelegate().alloc().init()
        NSApp().setDelegate_(delegate)
        self.workspace = NSWorkspace.sharedWorkspace()
        AppHelper.runEventLoop()

    def cancel(self):
        AppHelper.stopEventLoop()

    def handler(self, event):

        try:
            activeApps = self.workspace.runningApplications()
            for app in activeApps:
                if app.isActive():
                    if app.localizedName() != self.currentApp:
                        self.currentApp = app.localizedName()
                        options = kCGWindowListOptionOnScreenOnly 
                        windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID)

                        for window in windowList:
                            if window['kCGWindowOwnerName'] == self.currentApp:
                                geom = window['kCGWindowBounds'] 
                                self.screen_hook( event=event,
                                                name = window['kCGWindowName'],
                                                owner = window['kCGWindowOwnerName'],
                                                x = geom['X'], 
                                                y = geom['Y'], 
                                                w = geom['Width'], 
                                                h = geom['Height'])
                                break
                    break

            loc = NSEvent.mouseLocation()

            # mouse clicky buttons
            if event.type() in ( NSLeftMouseDown, NSRightMouseDown, NSLeftMouseUp, NSRightMouseUp):
                self.mouse_button_hook(event=event, x=loc.x, y=loc.y)

            # mouse scrolly buttons 
            elif event.type() == NSScrollWheel:
                if event.deltaY() > 0 and event.deltaY() < 0:
                    self.mouse_button_hook(event=event, x=loc.x, y=loc.y)
                if event.deltaX() > 0 and event.deltaX() < 0:
                    self.mouse_button_hook(event=event, x=loc.x, y=loc.y)

            # keys down
            elif event.type() in ( NSKeyDown, NSKeyUp ):

                flags = event.modifierFlags()
                modifiers = [] # OS X api doesn't care it if is left or right
                if (flags & NSControlKeyMask):
                    modifiers.append('CONTROL')
                if (flags & NSAlternateKeyMask):
                    modifiers.append('ALTERNATE')
                if (flags & NSCommandKeyMask):
                    modifiers.append('COMMAND')

                self.key_hook(event=event, key=event.keyCode(), char=keycode.tostring( event.keyCode() ), mods=modifiers, is_repeat=event.isARepeat())

            # Mouse moved
            elif event.type() == NSMouseMoved:
                self.mouse_move_hook(event=event, x=loc.x, y=loc.y)
            else:
                pass

        except ( KeyboardInterrupt ) as e:
            print 'handler', e
            AppHelper.stopEventLoop()

if __name__ == '__main__':
    sc = SniffCocoa()
    sc.run()



回答2:


For using Keycode module. Just clone it from here and run "sudo setup.py install" . You will have keycode module https://github.com/abarnert/pykeycode



来源:https://stackoverflow.com/questions/12389665/python-capture-keystrokes-values-in-text-file-on-os-x

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!