Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6744e0525a | |||
| f1879726d9 | |||
| 56f3b54f62 | |||
| 11fadb16fd | |||
| 2340833bb8 | |||
| 7ce4cb5050 | |||
| 78e5dd1f4e | |||
| 857f68ef6b | |||
| 14c3cb49b9 | |||
| a6d32ecddb | |||
| e5e02401da | |||
| ea3eac3c40 | |||
| 28a8112c6d | |||
| 45384106c8 | |||
| 81729f57cc | |||
| 7ecfcad239 | |||
| b2929a9e92 | |||
| 6d33c7ff1e | |||
| 5687fbc8b2 | |||
| 9e356b1b0a | |||
| f7b94b3e57 |
@@ -4,6 +4,11 @@ Release History
|
||||
master
|
||||
------
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fix library discovery on Windows. [#32](https://github.com/camelot-dev/camelot/pull/32) by [KOLANICH](https://github.com/KOLANICH).
|
||||
* Fix calling convention of callback functions. [#34](https://github.com/camelot-dev/camelot/pull/34) by [KOLANICH](https://github.com/KOLANICH).
|
||||
|
||||
0.7.3 (2019-07-07)
|
||||
------------------
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ $ conda install -c conda-forge camelot-py
|
||||
|
||||
### Using pip
|
||||
|
||||
After [installing the dependencies](https://camelot-py.readthedocs.io/en/master/user/install-deps.html) ([tk](https://packages.ubuntu.com/trusty/python-tk) and [ghostscript](https://www.ghostscript.com/)), you can simply use pip to install Camelot:
|
||||
After [installing the dependencies](https://camelot-py.readthedocs.io/en/master/user/install-deps.html) ([tk](https://packages.ubuntu.com/bionic/python/python-tk) and [ghostscript](https://www.ghostscript.com/)), you can simply use pip to install Camelot:
|
||||
|
||||
<pre>
|
||||
$ pip install camelot-py[cv]
|
||||
@@ -132,4 +132,8 @@ Camelot uses [Semantic Versioning](https://semver.org/). For the available versi
|
||||
|
||||
This project is licensed under the MIT License, see the [LICENSE](https://github.com/camelot-dev/camelot/blob/master/LICENSE) file for details.
|
||||
|
||||
<img src="http://i65.tinypic.com/9h4ajs.png" align="centre" />
|
||||
## Support the development
|
||||
|
||||
You can support our work on Camelot with a one-time or monthly donation [on OpenCollective](https://opencollective.com/camelot). Organizations who use camelot can also sponsor the project for an acknowledgement on [our documentation site](https://camelot-py.readthedocs.io/en/master/) and this README.
|
||||
|
||||
Special thanks to all the users, organizations and contributors that support Camelot!
|
||||
|
||||
@@ -81,7 +81,9 @@ def delete_instance(instance):
|
||||
"""
|
||||
return libgs.gsapi_delete_instance(instance)
|
||||
|
||||
|
||||
if sys.platform == "win32":
|
||||
c_stdstream_call_t = WINFUNCTYPE(c_int, gs_main_instance, POINTER(c_char), c_int)
|
||||
else:
|
||||
c_stdstream_call_t = CFUNCTYPE(c_int, gs_main_instance, POINTER(c_char), c_int)
|
||||
|
||||
|
||||
@@ -243,6 +245,9 @@ def __win32_finddll():
|
||||
|
||||
if sys.platform == "win32":
|
||||
libgs = __win32_finddll()
|
||||
if not libgs:
|
||||
import ctypes.util
|
||||
libgs = ctypes.util.find_library("".join(("gsdll", str(ctypes.sizeof(ctypes.c_voidp) * 8), ".dll"))) # finds in %PATH%
|
||||
if not libgs:
|
||||
raise RuntimeError("Please make sure that Ghostscript is installed")
|
||||
libgs = windll.LoadLibrary(libgs)
|
||||
|
||||
+22
-17
@@ -2,6 +2,7 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import copy
|
||||
|
||||
from PyPDF2 import PdfFileReader, PdfFileWriter
|
||||
|
||||
@@ -89,50 +90,55 @@ class PDFHandler(object):
|
||||
P.extend(range(p["start"], p["end"] + 1))
|
||||
return sorted(set(P))
|
||||
|
||||
def _save_page(self, filepath, page, temp):
|
||||
def _save_pages(self, filepath, pages, temp):
|
||||
"""Saves specified page from PDF into a temporary directory.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filepath : str
|
||||
Filepath or URL of the PDF file.
|
||||
page : int
|
||||
Page number.
|
||||
pages : int
|
||||
Page numbers.
|
||||
temp : str
|
||||
Tmp directory.
|
||||
|
||||
"""
|
||||
with open(filepath, "rb") as fileobj:
|
||||
infile = PdfFileReader(fileobj, strict=False)
|
||||
if infile.isEncrypted:
|
||||
infile.decrypt(self.password)
|
||||
fpath = os.path.join(temp, "page-{0}.pdf".format(page))
|
||||
infile_original = PdfFileReader(fileobj, strict=False)
|
||||
if infile_original.isEncrypted:
|
||||
infile_original.decrypt(self.password)
|
||||
|
||||
for page in pages:
|
||||
# Ensure PdfFileReader object is unmodified
|
||||
infile = copy.copy(infile_original)
|
||||
fpath = os.path.join(temp, 'page-{0}.pdf'.format(page))
|
||||
froot, fext = os.path.splitext(fpath)
|
||||
p = infile.getPage(page - 1)
|
||||
outfile = PdfFileWriter()
|
||||
outfile.addPage(p)
|
||||
with open(fpath, "wb") as f:
|
||||
with open(fpath, 'wb') as f:
|
||||
outfile.write(f)
|
||||
|
||||
# Orient rotated pages correctly
|
||||
layout, dim = get_page_layout(fpath)
|
||||
# fix rotated PDF
|
||||
chars = get_text_objects(layout, ltype="char")
|
||||
horizontal_text = get_text_objects(layout, ltype="horizontal_text")
|
||||
vertical_text = get_text_objects(layout, ltype="vertical_text")
|
||||
rotation = get_rotation(chars, horizontal_text, vertical_text)
|
||||
if rotation != "":
|
||||
fpath_new = "".join([froot.replace("page", "p"), "_rotated", fext])
|
||||
if rotation != '':
|
||||
fpath_new = ''.join([froot.replace('page', 'p'), '_rotated', fext])
|
||||
os.rename(fpath, fpath_new)
|
||||
infile = PdfFileReader(open(fpath_new, "rb"), strict=False)
|
||||
infile = PdfFileReader(open(fpath_new, 'rb'), strict=False)
|
||||
if infile.isEncrypted:
|
||||
infile.decrypt(self.password)
|
||||
outfile = PdfFileWriter()
|
||||
p = infile.getPage(0)
|
||||
if rotation == "anticlockwise":
|
||||
if rotation == 'anticlockwise':
|
||||
p.rotateClockwise(90)
|
||||
elif rotation == "clockwise":
|
||||
elif rotation == 'clockwise':
|
||||
p.rotateCounterClockwise(90)
|
||||
outfile.addPage(p)
|
||||
with open(fpath, "wb") as f:
|
||||
with open(fpath, 'wb') as f:
|
||||
outfile.write(f)
|
||||
|
||||
def parse(
|
||||
@@ -161,8 +167,7 @@ class PDFHandler(object):
|
||||
"""
|
||||
tables = []
|
||||
with TemporaryDirectory() as tempdir:
|
||||
for p in self.pages:
|
||||
self._save_page(self.filepath, p, tempdir)
|
||||
self._save_pages(self.filepath, self.pages, tempdir)
|
||||
pages = [
|
||||
os.path.join(tempdir, "page-{0}.pdf".format(p)) for p in self.pages
|
||||
]
|
||||
|
||||
@@ -30,6 +30,9 @@ Release v\ |version|. (:ref:`Installation <install>`)
|
||||
.. image:: https://badges.gitter.im/camelot-dev/Lobby.png
|
||||
:target: https://gitter.im/camelot-dev/Lobby
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/ambv/black
|
||||
|
||||
**Camelot** is a Python library that makes it easy for *anyone* to extract tables from PDF files!
|
||||
|
||||
.. note:: You can also check out `Excalibur`_, which is a web interface for Camelot!
|
||||
@@ -83,6 +86,13 @@ See `comparison with other PDF table extraction libraries and tools`_.
|
||||
.. _ETL and data analysis workflows: https://gist.github.com/vinayak-mehta/e5949f7c2410a0e12f25d3682dc9e873
|
||||
.. _comparison with other PDF table extraction libraries and tools: https://github.com/camelot-dev/camelot/wiki/Comparison-with-other-PDF-Table-Extraction-libraries-and-tools
|
||||
|
||||
Support us on OpenCollective
|
||||
----------------------------
|
||||
|
||||
If Camelot helped you extract tables from PDFs, please consider supporting its development by `becoming a backer or a sponsor on OpenCollective`_!
|
||||
|
||||
.. _becoming a backer or a sponsor on OpenCollective: https://opencollective.com/camelot
|
||||
|
||||
The User Guide
|
||||
--------------
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ The easiest way to install Camelot is to install it with `conda`_, which is a pa
|
||||
|
||||
$ conda install -c conda-forge camelot-py
|
||||
|
||||
.. note:: Camelot is available for Python 2.7, 3.5 and 3.6 on Linux, macOS and Windows. For Windows, you will need to install ghostscript which you can get from their `downloads page`_.
|
||||
.. note:: Camelot is available for Python 2.7, 3.5, 3.6 and 3.7 on Linux, macOS and Windows. For Windows, you will need to install ghostscript which you can get from their `downloads page`_.
|
||||
|
||||
.. _conda: https://conda.io/docs/
|
||||
.. _Anaconda: http://docs.continuum.io/anaconda/
|
||||
|
||||
Reference in New Issue
Block a user