Python
Selenium
スクレイピング

newspicksで自分がpickしたニュースのスクレイピング

はじめに

NewsPicksを使ってpickしたニュースを保存したくなったので、マイページ上からスクレイピングするスクリプトを書きました。javascriptが実行されているページだったので、一応後で拡張できるようにseleniumを使いました。今回は当日pickした情報のみをスクレイピングします。

集めた情報はpickしたニュースの以下のデータです。

  • url
  • タイトル
  • 自分のコメント
  • 日時が分かるモノ

NewsPicksへのログインとマイページ情報の取得

import requests
from selenium import webdriver
import time
import datetime

class NPscraping():

    def __init__(self, user_id, password):
        self.base_url = "https://newspicks.com/"
        self.user_id = user_id
        self.password = password


    def get_today_news(self):
        driver = webdriver.PhantomJS()
        driver.set_window_size(1920, 1080)
        driver.get(self.base_url)
        driver.find_element_by_class_name("login").click()
        driver.find_element_by_id('login-username').send_keys(self.user_id)
        driver.find_element_by_id('login-password').send_keys(self.password)
        driver.find_element_by_class_name("login-btn").click()
        time.sleep(5)

        driver.find_element_by_class_name("user-header").click()

        return self.get_news_cards(driver)



    def get_news_cards(self, driver):
        news_cards = []
        today_str = datetime.date.today().strftime('%Y%m%d') #今日の日付

        for card in driver.find_elements_by_class_name('news-card'):
            if card.get_attribute('data-key')[0:8] != today_str: #今日の日付と同じものだけ
                break

            news_cards.append({
                'url': card.find_element_by_tag_name("a").get_attribute("href"),
                'title': card.find_element_by_tag_name("a").find_element_by_class_name("title").text,
                'comment': card.find_element_by_class_name("user-comment").find_element_by_class_name("comment").text,
                'data-key': card.get_attribute('data-key')
            })

        return news_cards

色々機能をつけようと思ったのでクラスにしましたが、特にクラスにする必要はないと思います。

  • PhantomJSを使ってNewspickのログインページに入り、"login"class要素のボタンを情報を入力してクリック。
  • 続いて、"user-header"class要素がマイページに繋がる要素なのでクリック
  • today_strに本日の日付をNewsPicksのフォーマットを合わせて保存
  • "news-card"class要素の'data-key'要素から日付を比較
  • 後は"news-card"class要素の中から必要なデータをdict変数に保存

という流れになっています。(地味にどのclass要素がマイページに繋がるのが見つけるのがしんどかったです)

user_id = <newspickid>
password = <newspickspass>

np = NPscraping(user_id, password)
news_cards = np.get_today_news()

で本日pickしたニュースをdictのlistで入手できます。オブジェクト化した意味はないと思いますが、とりあえず入手はできます。(オブジェクト指向よく分かってないです...)

今後

今回のスクレイピングは自分で情報を保管したり編集したり、ブログに自動で投稿できるようにするためにデータ化したものです。自分としては、はてなブログの下書きに毎日投稿して、自分のニュース閲覧を管理・公開をしたいと思っています。

追記

上のコードだと、自分のコメントのデータを取る時画面に表示されてるコメントしか取れません。(多分)60文字以上のコメントは省略されてしまうからです。なので

'comment': card.find_element_by_class_name("user-comment").find_element_by_class_name("comment").text,

ではなくて

'comment': card.find_element_by_class_name("user-comment").find_element_by_class_name("comment").get_attribute("data-org")

にする必要があります。省略されてる場合はdata-orgというattributeが存在するようになるので、そのような場合わけをするだけで取得できます。