山傘のプログラミング勉強日記

プログラミングに関する日記とどうでもよい雑記からなるブログです。

Pythonクローリング&スクレイピング[増補改訂版] ―データ収集・解析のための実践開発ガイドー その3

第 2 章 Python ではじめるクローリング・スクレイピング

lxml でスクレイピング

HTML の要素に簡単にアクセスするために、lxml を使います。

lxml の基本的な使用方法 - Python 入門

import lxml.html
import requests

tmp = requests.get("https://gihyo.jp/dp")
html = lxml.html.fromstring(tmp.text)

# href 要素の URL を絶対 URL にする
html.make_links_absolute('https://gihyo.jp/')

for a in html.cssselect('#listBook > li > a[itemprop="url"]'):
    url = a.get('href')
    p = a.cssselect('p[itemprop="name"]')[0]
    title = p.text_content()
    print(url, title)

csv 形式で保存する

import csv

# 改行コードの自動変換を防ぐために、newline=''と指定する
with open('top_cities.csv', 'w', newline='') as f:
  writer = csv.writer(f)
  writer.writerow(['rank', 'city', 'population'])
  writer.writerow([
    [1, '東京', 9272000],
    [2, '神奈川', 3724000],
    [3, '大阪', 2691000],
  ])

json 形式で出力する

import json

cities = [
  {'rank': 1, 'city': '東京', 'population': 9272000},
  {'rank': 2, 'city': '神奈川', 'population': 3724000},
  {'rank': 3, 'city': '大阪', 'population': 2691000},
]

print(json.dumps(cities))

技術評論社 のサイトの書籍情報を保存する

import csv
from typing import List
import requests
import lxml.html

def main():

  url = 'http://gihyo.jp/dp'
  html = fetch(url)
  books = scrape(html, url)
  save('books.csv', books)


def fetch(url: str) -> str:
  """
  引数urlのWEBページを取得し、str型のHTMLを返す
  """
  req = requests.get(url)
  return req.text


def scrape(html: str, base_url: str) -> List[dict]:
  """
  html から書籍の情報を抜き出しListを返す
  """
  books = []
  html = lxml.html.fromstring(html)
  html.make_links_absolute(base_url) # 全てのa要素のhref属性を絶対URLに変換する
  
  for a in html.cssselect('#listBook > li > a[itemprop="url"]'):
    url = a.get('href')
    p = a.cssselect('p[itemprop="name"]')[0]
    title = p.text_content()
    books.append({'url': url, 'title': title})

  return books


def save(file_path: str, books: List[dict]):
  """
  書籍のリストをCSV形式で保存する
  """
  with open(file_path, 'w', newline='') as f:
    writer = csv.DictWriter(f, ['url', 'title'])
    writer.writeheader()
    writer.writerows(books)

if __name__ == '__main__':
  main()

感想

HTML ファイルから要素を抜き出し、CSV 形式で保存することをやりました。基本的なことが要求されていると思うので、使い方を覚えていきたいと思います。