14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Google Drive上のファイルをOCRする

Last updated at Posted at 2019-04-11

Google Driveで、Drive上のPDFや画像ファイルを「Google Documentで開く」すると、元ファイルがGoogle Documentに変換され、そこからテキストだけを抽出できるようになります。

Drive APIでも Files: create https://developers.google.com/drive/api/v3/reference/files/create の機能を使ってファイルをGoogle Documentとしてアップロードすることで、同様のことができます。

当然Drive上のファイルをAPIからGoogle Documentに変換することもできると思ってAPIを眺めたら、たぶん Files: export https://developers.google.com/drive/api/v3/reference/files/export に最初は目が行きますが、これだと 元ファイルがGoogle Documentである という条件があり、目的の画像やPDFのOCRではなさそうです。Files: get を使うのか?とも思いますが、これは単純にダウンロードしてしまうものなので、Files:Exportと同じことになりそうです。

でもできないことはないだろうと探したところ Files: Copy https://developers.google.com/drive/api/v3/reference/files/copy を使い、コピー先のファイルの mimetypeapplication/vnd.google-apps.document に指定することで、Drive上だけでOCR(Google Documentへの変換)が可能でした。

下記はServiceAccountでjsonのキーファイル(serviceaccount.jsonで保存)を保存して、Drive上のファイルをGoogle Documentに変換してテキストを抜きだすサンプルです。

package ocr

import (
	"io/ioutil"
	"log"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/docs/v1"
	"google.golang.org/api/drive/v3"
)

func copyFileAsGoogleDocument(fileID string) (*drive.File, error) {
	driveService, err := newDriveService()
	if err != nil {
		return nil, err
	}
	dst := &drive.File{
		Name:     fileID + "_copied_document",
		MimeType: "application/vnd.google-apps.document",
	}
	return driveService.Files.Copy(fileID, dst).Do()
}
func extractText(documentID string) (string, error) {
	docsService, err := newDocsService()
	if err != nil {
		return "", err
	}
	document, err := docsService.Documents.Get(documentID).
		Fields("body/content/paragraph/elements/textRun/content", "title").
		Do()
	if err != nil {
		return "", err
	}

	text := ""
	for _, content := range document.Body.Content {
		if content.Paragraph == nil || content.Paragraph.Elements == nil {
			continue
		}
		for _, paragraphElement := range content.Paragraph.Elements {
			if paragraphElement.TextRun == nil {
				continue
			}
			text = text + paragraphElement.TextRun.Content
		}
	}
	return text, nil
}
func deleteFile(fileID string) error {
	driveService, err := newDriveService()
	if err != nil {
		return err
	}
	return driveService.Files.Delete(fileID).Do()
}

func newDriveService() (*drive.Service, error) {
	conf, err := google.JWTConfigFromJSON(jwt, drive.DriveScope)
	if err != nil {
		return nil, err
	}
	return drive.New(conf.Client(oauth2.NoContext))
}
func newDocsService() (*docs.Service, error) {
	conf, err := google.JWTConfigFromJSON(jwt, docs.DocumentsScope)
	if err != nil {
		return nil, err
	}
	return docs.New(conf.Client(oauth2.NoContext))
}

var jwt []byte

func init() {
	bytes, err := ioutil.ReadFile("serviceaccount.json")
	if err != nil {
		log.Fatalf("%#v", err)
	}
	jwt = bytes
}
package ocr

import "testing"

func TestOCR(t *testing.T) {
	fileID := "対象のファイルID"

	copy, err := copyFileAsGoogleDocument(fileID)
	if err != nil {
		t.Fatalf("%v", err)
	}
	defer deleteFile(copy.Id)

	text, err := extractText(copy.Id)
	t.Logf("%v", text)
}
14
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?