How do I get per-vertex tangents (and bitangents) in my export script?
How do I translate this per-corner/per-face data into per-vertex?


You get the appropriate vertex of the face loop this way:

import bpy

me = bpy.context.active_object.data

for face in me.polygons:
    # face loops and face vertices are in the same order
    for vert_id, loop_id in zip(face.vertices, face.loop_indices):    
        # this is the loop:
        me.loops[loop_id]
        # this is the vertex in the corner of the loop:
        me.vertices[vert_id]



  Should I be storing bitangents in my vertex buffer from this stage, or calculate them in the fragment shader?


This depends on what you want to do with your engine. You can trade some memory for faster fragment shader, but you loose a lot of functionality in the future.

If you need any mesh deformations (armature, soft-body,..) you will have to calculate normals, tangents and bitangents on the fly anyway.