@alex-woolford: In general, perfect extraction of data (with or without the same formatting that you see in the PDF) is not always possible, thought it is, to some extent less than 100%. I'm saying this based on having worked on a similar project to yours, earlier. I came across similar issues to what you have, and some research on the Net showed that PDF in general is not a perfectly reversible format, i.e. it is not always possible to recover the text and format from a PDF with 100% accuracy. Sometimes characters even get lost, or transposed, and so on, during the extraction process (using some library). This seems to be due to the very nature of the PDF format and specification. It is not a text-based format. It is a derivative of PostScript and has some weird rules about layout of data. And this is according to official PDF documents, or according to the sites of product companies who have been working with PDF for a long time, and whose products are well known.
If less than perfect accuracy is tolerable, there are some products available (thought I don't know of any for Python, as of now). One is xpdf and another is PDFTextStream. I've used the former, not the latter. xpdf is a C library and also has command-line tools. PDFTextStream is a Java tool/library. It was a paid product earlier, but last I checked, it is now free for single-threaded applications, IIRC.
Even though xpdf is for C and PDFTextStream is for Java, you could call them from Python via XML-RPC or some other distributed computing / cross-language communication approach such as sockets. Some work would be involved, for that, of course.
HTH.