プログラミング的な

【Python入門】スクレイピングで複数のPDFデータをダウンロードし、一つのPDFにまとめる方法

ウェブ上で資料を探していて、見つけることはできたけど、PDF資料が分割掲載されたいたときに、一つ一つをクリックしてダウンロードしていたんですが、一括でダウンロードできて、かつ一つの資料として合体出来たら読むのに便利かなと思いPythonで組み立ててみました。(上手ではありませんがお許しください。)

以前PDFの分割方法も行ってみましたのでそちらも参照してください。

あわせて読みたい
Python入門:PDFを分割する先日グリーン・ニューディールのブログで最後のほうに参考PDFのリンクを貼っておいたのですが、そのPDFをプリントアウトしようとしたときに...

今回は愛知県庁の予算に関する資料を集めたかったので、以下のページを使用しました。

流れはこんな感じです。

  • BeautifulSoupを使い、aタグとhref属性を指定して取得する。
  • 上記サイトではPDFリンクが相対パスになっているので絶対パスに変更する。
  • リンクにはPDF以外も含まれるので、PDFに限定してリスト化する。
  • 一つのファイル内にダウンロードする。
  • ファイル内のPDFをまとめて一つのPDFに合体させる。

複数のPDFデータをダウンロードし、一つのPDFにまとめる方法

BeautifulSoupとurllib.request

BeautifulSoupはPythonでスクレイピングするときに欠かせないライブラリです。主にHTMLやXMLを解析するライブラリです。BeautiflSoupにはダウンロード機能はありません。

データにアクセス、もしくはダウンロードを行いたいときはurllibライブラリを使います。その中でurllib.requestモジュールはウェブサイトにあるデータにアクセスする機能を提供してくれます。

from bs4 import BeautifulSoup
import urllib.request as req
import urllib
url = "https://www.pref.aichi.jp/soshiki/zaisei/heisei28nendotousyoyosangianntou.html"
res = req.urlopen(url)
soup = BeautifulSoup(res, "html.parser")
result = soup.select("a[href]")
print(result)

resultを見てみると、確かにaタグhref属性を取り出すことができています。しかし、PDFデータの部分を見てみると「”/uploaded/attachment/208329.pdf”」のように相対パスになっています。これではダウンロードできないので相対パスを絶対パスに変更します。

相対パスを絶対パスにする

ベース部分のパス(ここでは「”https://www.pref.aichi.jp”」)を指定し、urllib.parse.urljoin()を使用して絶対パスに変換します。

from urllib.parse import urljoin
base = "https://www.pref.aichi.jp"
li = []
for link in result:
    href = link.get('href')
    url_1 = urljoin(base, href)
    li.append(url_1)

urljoin(base, href)でbaseで指定したURLとhrefタグで取得したパスを接続するという作業を行っています。そしてすべてのパスをリストに入れています。

次に、PDFデータのリンクのみを取得します。

リンクにはPDF以外も含まれるので、PDFに限定してリスト化する

urlに指定したウェブサイト内のaタグリンクをすべて取得しているのですが、今回欲しいのはその中のPDFデータだけなので、次に文字「pdf」を含むリンクだけを取り出します。

a = [s for s in li if s.endswith('pdf')]

変数名liの中から、「pdf」とついているリンクのみを取り出しています。

これで、上記ウェブサイト内のPDFデータのリンクのみを取り出すことができました。

つぎに、リンクにアクセスしPDFデータをダウンロードします。

一つのファイル内にダウンロードする

ファイルのダウンロードにはurlretrieveを使います。
ここでは、デスクトップの「aichi」ディレクトリ内に「愛知県予算」というディレクトリを用意しその中にすべて入れていきます。

urllib.request.urlretrieve(a[0],'C:/Users/ken_2/Desktop/aichi/愛知県予算/0.pdf' )
urllib.request.urlretrieve(a,'C:/Users/Desktop/aichi/愛知県予算/1.pdf' )
~省略~
urllib.request.urlretrieve(a[30],'C:/Users/Desktop/aichi/愛知県予算/30.pdf' )
urllib.request.urlretrieve(a[31],'C:/Users/Desktop/aichi/愛知県予算/31.pdf' )

本当は、for文などで簡略化したかったのですが、いい方法を書くことができず、すべてを一行づつ書いていってしまいました。
これで、PDFファイルのダウンロードに成功しました。今回のPDF資料は一つの財政資料として読みたいので、31個あるPDFファイルを結合させます。

ディレクトリ内のすべてのPDFファイルを一つに結合する

結合するにはPyPDF2モジュールとglobモジュールを使用します。結合したいファイルと保存ファイル名を指定することで結合できるクラスです。

import PyPDF2
import glob
import os
def combining_pdf(file_path, save_path):
    l = glob.glob(os.path.join(file_path, '*.pdf'))
  merger = PyPDF2.PdfFileMerger()
    for p in l:
        if not PyPDF2.PdfFileReader(p).isEncrypted:
            merger.append(p)
  merger.write(save_path)
    merger.close()
combining_pdf('C:/Users/Desktop/aichi/愛知県予算', 'C:/Users/Desktop/aichi/愛知財政資料.pdf')

ここでは、上記でPDFファイルを保存した「愛知県予算」ディレクトリにアクセスし、全PDFファイルを「愛知県財政資料.pdf」として結合・保存しています。

これで、複数のPDFデータを一つのPDFデータとして読むことができました。今回は全部のPDFデータを結合しましたが、必要なデータだけでも結合できたら便利なのでこの方法は役立ちそうです。

以上、

【Python入門】スクレイピングで複数のPDFデータをダウンロードし、一つのPDFにまとめる方法

でした。