LoginSignup
32
59

More than 5 years have passed since last update.

スクレイピングのサンプル

Last updated at Posted at 2017-03-16

yahoo!ニュースのタイトルを取得

from urllib.request import urlopen
from bs4 import BeautifulSoup
from pprint import pprint

URL = 'http://news.yahoo.co.jp/'
with urlopen(URL) as res:
  html = res.read().decode("utf-8")

soup = BeautifulSoup(html, 'html.parser')

titles = soup.select('.ttl a') # domを取得
titles = [t.contents[0] for t in titles] # テキストを取得
pprint(titles)
出力結果
>>>
['トランプ氏「司法行き過ぎ」',
 'PKO日報 特別防衛監察を指示',
 '病院で投与ミス 一時心肺停止',
 '特攻服の中学生ら200人 福岡',
 'オランダ 与党が第1党維持へ',
 'WBCで確率32万分の1の珍事',
 '中居の熱愛 事務所否定せず',
 '渡瀬さん 最強伝説と兄の存在']

BeautifulSoup4の要素選択メソッドには、
find,find_allもあるが、selectを使うことが多い。

テキストの取得でnoneが返ってくる場合、
.string,.text,.contents[0]など試してみる
http://stackoverflow.com/questions/20750852/beautifulsoup-4-python-string-returns-none

天気予報を取得し、CSV/JSONとして保存

天気を取得

from urllib.request import urlopen
from bs4 import BeautifulSoup
from pprint import pprint
import csv
import re

tenki = []
URL = "http://weather.livedoor.com/forecast/rss/area/130010.xml"

with urlopen(URL) as res:
  html = res.read().decode("utf-8")

soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all("item"):
    title = item.find("title").string
    if title.find("[ PR ]") == -1: # ゴミ削除
        text = re.sub(r'\[?.+\]\s', '', title) # []内を削除
        result = text.split(' - ')
        tenki.append(result)
pprint(tenki)
出力結果
>>>
[['東京', '曇り', '最高気温℃', '7月23日(日)'],
 ['東京', '曇り', '最高気温32℃', '7月24日(月)'],
 ['東京', '曇り', '最高気温34℃', '7月25日(火)'],
 ['東京', '曇時々晴', '最高気温33℃', '7月26日(水)'],
 ['東京', '曇時々晴', '最高気温31℃', '7月27日(木)'],
 ['東京', '曇時々晴', '最高気温32℃', '7月28日(金)'],
 ['東京', '曇時々晴', '最高気温32℃', '7月29日(土)'],
 ['東京', '曇時々晴', '最高気温32℃', '7月30日(日)']]

基本html.parserにする
lxml.parserはたまにエラーがあるらしい
https://www.crummy.com/software/BeautifulSoup/bs4/doc/

CSVとして保存

with open('weather.csv','w',newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['city','status','max','date'])
    writer.writerows(tenki)
weather.csv
place,status,max,date
東京,曇り,最高気温℃,7月23日(日)
東京,曇り,最高気温32℃,7月24日(月)
東京,曇り,最高気温34℃,7月25日(火)
東京,曇時々晴,最高気温33℃,7月26日(水)
東京,曇時々晴,最高気温31℃,7月27日(木)
東京,曇時々晴,最高気温32℃,7月28日(金)
東京,曇時々晴,最高気温32℃,7月29日(土)
東京,曇時々晴,最高気温32℃,7月30日(日)

CSV->JSON

rows = []
csvfile = open('weather.csv', 'r')
jsonfile = open('weather.json', 'w')
fieldnames = ('city','status','max','date')
reader = csv.DictReader(csvfile, fieldnames)
for index,row in enumerate(reader):
    if(index == 0): continue #  {"city": "city" ...} という表記は不要
    rows.append(row)
json.dump(rows, jsonfile, ensure_ascii=False, indent=2)
weather.json
[
  {
    "date": "7\u670823\u65e5(\u65e5)",
    "status": "\u66c7\u308a",
    "city": "\u6771\u4eac",
    "max": "\u6700\u9ad8\u6c17\u6e29\u2103"
  },
  {
    "date": "7\u670824\u65e5(\u6708)",
    "status": "\u66c7\u308a",
    "city": "\u6771\u4eac",
    "max": "\u6700\u9ad8\u6c17\u6e2932\u2103"
  },
  ...
]

ics.mediaの新着記事の画像を取得、ローカルに保存

# ics.mediaをスクレイピング
import os
from urllib.request import urlopen
from bs4 import BeautifulSoup

URL = "https://ics.media/"
with urlopen(URL) as res:
    html = res.read().decode("utf-8")

soup = BeautifulSoup(html, "html.parser")

# 新着記事の画像(とタイトル)を取得
topics = soup.select(".topicsContainer")[0].nextSibling
topics_urls = topics.select(".thumb img")
topics_ttls = topics.select(".entryTitle a")
img_urls = [e["src"] for e in topics_urls]
img_ttls = [e.string for e in topics_ttls]

"""
# 相対パスの場合、絶対パスに変換
# リスト内包表記、三項演算子
img_urls = [u if u.find("http") == 0 else URL + u for u in img_urls]
"""

# 保存
img_dir = "images"
if not os.path.exists(img_dir):
    os.mkdir(img_dir)

for i,url in enumerate(img_urls):
    print("記事"+str(1+i), img_ttls[i])
    print(url)
    with urlopen(url) as res:
        img = res.read()
        with open(img_dir + "/entry_image%d.png" % (i+1), "wb") as f:
            f.write(img)
出力結果
>>>
記事1 ウェブ制作者なら意識してほしいCSS設計の基礎知識
https://ics.media/wp-content/uploads/2017/03/170315_eyecatch-640x256.jpg
記事2 CSS3だけで表現! コピペで使えるマイクロインタラクション作りました
https://ics.media/wp-content/uploads/2017/03/main-640x256.png
記事3 広告系ウェブサイトのクオリティーが凄い! 最近話題になった国内サイト5選
https://ics.media/wp-content/uploads/2017/03/170227_web_trend_1611_1702_eye-640x256.jpg
・・・(略)・・・

兄弟要素の取得
http://tdoc.info/beautifulsoup/

osモジュール
https://docs.python.jp/3/library/os.html

enumerate関数 インデックスとともにループ
http://python.civic-apps.com/zip-enumerate/

JavaScriptでDOMをレンダリングしているサイトから取得

chrome dev tool
Settings > Preferences > Debugger > Disable JavaScript

JSを無効にした上でリロードして要素が消えたら、
DOMがJSで動的に生成されているサイト

今回はPhantomJSSeleniumを使う

$ brew install phantomjs
$ pip3 install —upgrade selenium

from selenium import webdriver
from bs4 import BeautifulSoup
from pprint import pprint

URL = "https://dokusho-ojikan.jp/original/#!top"

driver = webdriver.PhantomJS()
driver.get(URL)
html = driver.page_source

bs = BeautifulSoup(html, "html.parser")
img_urls = [img.get("src") for img in bs.select("#unique-pickup img")]
for u in img_urls:
    print(u)
出力結果
>>>
https://cdn.om.dokusho-ojikan.jp/img/1f387c10-a8f8-11e6-8a10-525431b7cd60.jpg
https://cdn.om.dokusho-ojikan.jp/img/98c2e066-9a44-11e5-9ae2-52540e2de543.png
https://cdn.om.dokusho-ojikan.jp/img/7adbba1b-344b-11e5-be53-5254f877f35f.jpg
・・・(略)・・・
32
59
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
32
59