やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Pythonニュース取得が遅いので、BeautifulSoup4のHTMLパーサをlxmlに変更した

 html.parserPython製のため遅いらしい。そこでC言語製のlxmlにすると高速だとか。

成果物

情報源

インストール

pip3 install lxml
Collecting lxml
  Using cached https://www.piwheels.org/simple/lxml/lxml-4.4.1-cp35-cp35m-linux_armv7l.whl
Installing collected packages: lxml
Successfully installed lxml-4.4.1

ついでにクラス化

 get_html.pyHtmlGetter.pyに変更した。関数からクラスにした。1URLあたりBeautifulSoupインスタンスが2回作成される場合があったが、1回になるようにした。

HtmlGetter.py

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
from bs4 import Comment
import time
import re

class HtmlGetter:
    def get(self, url, wait_second=1):
        self.__soup = BeautifulSoup(__get_html(url), 'html.parser')
        html = self.__get_more_link(str(self.__soup.html))
        html = self.__del_element(html)
        time.sleep(wait_second)
        return html
    def __get_html(self, url):
        options = Options()
        options.set_headless(True)
        driver = webdriver.Chrome(chrome_options=options)
        driver.get(url)
        return driver.page_source.encode('utf-8').decode('utf-8')
    # 「続きを読む」リンクがあるならそのURLを返す。なければ元のURLを返す
    def __get_more_link(self, html):
        link = self.__soup.find('a', text=re.compile(r'^.*続きを読む.*$'))
        return html if link is None else self.__get_html(link.get('href'))
    # 不要な要素を削除する
    def __del_element(self, html):
        self.__soup.find('head').decompose()
        for comment in self.__soup(text=lambda x: isinstance(x, Comment)): comment.extract()
        for script in self.__soup.find_all('script', src=False): script.decompose()
        for noscript in self.__soup.find_all('noscript'): noscript.decompose()
        return str(self.__soup.html)

 「続きを読む」リンクに関してはサイトの作りに依存するので、あまり当てにならない。

結果

 むしろ今回の対応で1〜2分ほど遅くなった。クラス化の影響か?

 もしボトルネックがネットワーク通信なら、誤差の範囲内か? だが、ブラウザでHTMLを見ているときは、20秒もかからない。一体、どこがそんなに遅いのか。前回は10分近くだったので20秒/1件だが、今回は約12分なので24秒/1件。

 パーサによる大差はないように見える。ネットでみかけた情報とは違う。これならhtml.parserでも十分。やはり自分で試してみないと信用できない。

パーサ 時間
lxml real 11m28.014s
html.parser real 12m27.681s

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux