2018年4月12日木曜日

BeautifulSoupでsoupをローカルに保存してから復元する

WebページをBeautifulSoupで.htmlに保存する

import pandas as pd
import urllib.request
from bs4 import BeautifulSoup

from selenium import webdriver
BeautifulSoupで使うhtmlを直接保存する方がベター(好みですが)
url = 'http://...some_url'
html = urllib.request.urlopen(url).read().decode('utf-8')
filename = "test.html"
f = open(filename, 'w')
f.write(html)
f.close() 
これでhtmlへの保存はOKです。

htmlを開いてsoupにする

filename = 'test'
with open(filename+'.html') as myfile:          
    soup = BeautifulSoup(myfile, 'html.parser')

2chのhtmlのとき

読み込みの問題で直接htmlは保存できないので、soupをhtmlに変換すればよいです。
browser = webdriver.Firefox()
browser.get(url)
soup= BeautifulSoup(browser.page_source, "lxml")
html = str(soup.contents)

soup の 内容を pandas -> to_csv でcsvにして保存

・soup.content[0] にして前後の [] を削除
・クォートを無しにする
import csv
import pandas as pd
savename = 'Test'
pd.DataFrame(str(soup.contents[0]).splitlines()).to_csv(
    savename+".csv",
    header=False,
    index=False,
    escapechar='\\',
    quoting=csv.QUOTE_NONE) 
※str(soup.contents[0]).splitlines()) は str(soup).splitlines() とやっても同じ結果になります。
戻すときは
tmp = pd.read_csv("./Test.csv",
            header=None,
            index_col=None,
            escapechar='\\',
            )
html_doc = ''.join(list(tmp.T.iloc[0]))
soup = BeautifulSoup(html_doc, 'html.parser')
とやるとpandas, html, soupの順に変換できます。

--ここからあまり意味なし--

soupを無理やりcsvにして保存したが1行1文字になる

def get_soup(url, quit=''):
   browser = webdriver.Firefox()
   browser.get(url)
   time.sleep(3)
   try:
       soup= BeautifulSoup(browser.page_source, "lxml")
   except:
       browser.quit()
こんな感じでsoupを得て、ローカルに保存したいとき。

下記の方法が紹介されていた。
https://stackoverflow.com/questions/40529848/how-to-write-the-output-to-html-file-with-python-beautifulsoup
with open("output1.html", "w") as file:
   file.write(str(soup))
・・・自分の環境ではできなかった。html側のJSの問題?

解決法として、
savedir = 'hoge'
savename = 'hogege'
pd.DataFrame(list(str(soup))).to_csv(savedir+savename+".csv", header=False, index=False) 
とやってstrにしてからlistにして保存。ちなみにこのcsvは直接読めません。
一文字ずつ保存してしまっているので、すごく無理矢理感があります。

復元するときは、
tmp = pd.read_csv(savedir+savename+".csv", index_col=0)
 html_doc = ''.join(list(tmp.T.iloc[0]))
soup = BeautifulSoup(html_doc, 'html.parser') 
(※ローカルで読むことは無想定。jupyterで読む)。

index=Flaseにしないとcsvの一列目にindexが入ってファイルが巨大になります。

0 件のコメント:

コメントを投稿