初めに
前回のスクレイピング(2)で、QiitaのJuliaタグページから、リンクとタイトルを取得しました。
この記事を書いた時点(2022/3/29)では、feedで公開された記事は20件でした。ところが2022/4/7以降、feedでは4件のみの公開になっています。内部での設定を変更したようです。そもそもfeedはwebにアクセスしなくても更新情報を取得できるようにし、それによって記事への動線を確保するためのものです。4件では1日の新着分にすらならないので、新着記事に到達することができません。何のためにこういう変更したのか訳が分かりません。(怒)
そこで今回は、上記のfeedを使わずに、juliaタグの新着記事を取得する方法を紹介します。
基本的には、次の記事に沿った方法と同じになりますが、当然ながら、URLやHTMLタグなどの指定が異なります。
なお、今回対象とするのは、「juliaタグが付いた記事を検索した結果を新着順に表示したページ」になります。1ページに10件が掲載されているので、新着20件を取得するために、2ページ目も取得対象とします。取得数を増やしたければ、URL中の「page=」の値を増やせば対応可能です。
このページは、HTMLのなかにURLとタイトルが表示されているので、通常のスクレイピングで情報が取得できます。
使用するパッケージ
- HTTP
- HTTPを操作する(WebAPIを呼び出す)
- https://segakuin.com/julia/http/
- https://github.com/JuliaWeb/HTTP.jl
- Gumbo
- HTMLを解析する
- https://segakuin.com/julia/gumbo/
- Cascadia
- CSSセレクタを扱う
- https://segakuin.com/julia/cascadia/
- URIs
- url操作を行う。パッケージ名に注意。
- https://github.com/JuliaWeb/URIs.jl
- Dates
- 日時操作(標準で組み込まれています)
- https://docs.julialang.org/en/v1/stdlib/Dates/
パッケージの追加
必要なパッケージを追加します。
julia> using Pkg
julia> Pkg.add("HTTP")
julia> Pkg.add("Gumbo")
julia> Pkg.add("Cascadia")
julia> Pkg.add("URIs")
HTMLの取得
指定URLからHTMLファイルを取得します。以下、1ページ目の取得についての説明を行います。
また、基本的な操作は以前の記事と同じなので、適宜省略します。
julia> using HTTP
julia> qiita_search_url = "https://qiita.com/search?q=tag%3Ajulia&sort=created"
julia> response = HTTP.request("GET", qiita_search_url)
julia> code = String(response.body) # Byte列を文字列に変換
HTMLファイルの解析
取得したHTMLを解析し、「head」タグと「body」タグを切り出します。
julia> using Gumbo
julia> doc = Gumbo.parsehtml(code)
julia> head = doc.root[1]
julia> body = doc.root[2]
CSSセレクターを用いた検索
CSSセレクターを使ってHTMLから必要な情報を検索します。
リンクを取得するので「a」タグの指定で検索できそうですが、本来必要としない情報まで含まれてしまいます。対象ページのHTMLソースを見ると「h1」タグの直下の「a」タグで、見出しとURLを取得できそうです。(HTMLの構造は、将来変更になる場合があります)
julia> using Cascadia
julia> qs = eachmatch(Selector("h1 a"), body)
変数qsに、aタグの一覧が格納されています。この時点では、タグのすべての記述を含んでいるので、必要な情報のみを抜き出します。
リストに格納されているので、for文で1件ずつ処理しています。1件のデータは次のようになっています。
julia> s = qs[1]
HTMLElement{:a}:<a href="/dnkit/items/8bfa4cad2cf3729fae37">
CUDAとプロセス並列化で爆速画像処理 with Julia
</a>
まず、URLを抜き出します。これは、aタグのhref属性の値を取得することに該当します。万が一、href属性がなかった場合に備え、ここではnothingを設定するように指定しておきます。(特定のURL、例えば404ページのURLなどを指定することもありそうです。)
julia> url = getattr(s, "href", nothing)
"/dnkit/items/8bfa4cad2cf3729fae37"
次に見出しを抜き出します。「nodeText()」を使って、タグ中のコンテンツとしての文字列を取得します。
julia> title = nodeText(s)
"CUDAとプロセス並列化で爆速画像処理 with Julia "
URLの補正
URLがいわゆる相対パスになっています。このままでは、不都合なので、URLを合成して絶対パスを作成します。
julia> using URIs
julia> qiita_search_url = "https://qiita.com/search?q=tag%3Ajulia&sort=created"
julia> new_url = resolvereference(qiita_search_url, url)
URI("https://qiita.com/dnkit/items/8bfa4cad2cf3729fae37")
julia> url_str = "$new_url"
"https://qiita.com/dnkit/items/8bfa4cad2cf3729fae37"
まとめ
上記をまとめたコードを下記に公開しています。
実行すると、日付付きのファイルにTSV形式で見出し+URLを出力します。
julialangjp/ScrapingQiitaSearchByJulia (Github)
参考記事
- Julia ウェブスクレイピング関連(Takahiro Koshiba’s HP)
- Juliaで楽しくWebスクレイピング!(@nezuq, Qiita)
- ガルパのスクレイピングをはじめよう~【Julia言語】(@rensF82, Qiita)
- ジュリアでウェブスクレイピングを行うにはどうすればよいですか?(CODE Q&A)
- Juliaでスクレイピング 1/m(眠気.jl)
- Scraping web pages with Julia and the HTTP and Gumbo packages(JULIA.SCHOOL)
- Pythonのseleniumライブラリを使ってJuliaLangでwebスクレイピング(snovaのブログ)
コメント