質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.36%

Python:htmlファイルの税込金額をすべて税抜金額に置換したい

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 680

score 18

前提・実現したいこと

htmlファイルの金額表示をすべて、「税込金額」 → 「税抜金額 + 税」という表記に変更したいのですが、
下記のソースコードでは、「'list' object has no attribute 'replace'」というエラーメッセージが出てしまい
置換できません。
リストでは置換できないという意味かと思ったのですが、どのように修正すれば良いのかがわからず
質問させていただきました。
ご教示いただければ幸いです。よろしくお願いいたします。

import re, os, glob, math
from pathlib import Path

path = '/Users/~~.html'

with open(path) as f:
    lines = f.readlines()
    lines_strip = [line.strip() for line in lines]
    before = [line.strip('<p class="b_price">''円</p>') for line in lines_strip if '<p class="b_price">' in line]  
    int_price = [int(x.replace(',','')) for x in before] 
    after = [str(math.ceil(int(x) / 1.08)) + '円 + 税' for x in int_price] 
    for row in before:
        columns_before = row.rstrip()

    for row in after:
        columns_after = row.rstrip()

    price = lines_strip.replace(columns_before, columns_after)

with open(file,'w') as f:
    f.write(price)
<!-- 商品一覧 -->
<div class="main">
    <div class="flex">
        <a href="item50.html"><img src="image/50.jpg"></a>
        <p class="b_name">商品50</p>    
        <p class="b_price">9,720円</p> <!-- 9,720円 → 9,000円+税 -->
    </div>

    <div class="flex">
        <a href="item60.html"><img src="image/60.jpg"></a>
        <p class="b_name">商品60</p>    
        <p class="b_price">8,640円</p><!-- 8,640円 → 8,000円+税 -->
    </div>

    <div class="flex">
        <a href="item62.html"><img src="image/62.jpg"></a>
        <p class="b_name">商品62</p>    
        <p class="b_price">7,560円</p><!-- 7,560円 → 7,000円+税 -->
    </div>

<!-- 以下続く -->

</div>

補足情報(FW/ツールのバージョンなど)

version:Python 3.6.5

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

readlines()じゃなくてread()で良くないですか?
あとpathlib使ってないですよね?read_textとか便利ですよ

import math
import re
from pathlib import Path

PATH = '/Users/~~.html'
TAX = 1.08

# 引数にmatchオブジェクトを受ける関数
def rep(m):
    # 後方参照(括弧の中)を参照して','消去
    value_with_tax = int(m.group(1).replace(',', ''))
    # 税抜
    value = math.ceil(value_with_tax / TAX)
    # カンマうち
    value_str = "{:,}".format(value)
    return f'<p class="b_price">{value_str}円+税</p>'


# Pathオブジェクトを作成
html = Path(PATH)
# テキストを読み込み
html_text= html.read_text()
# 正規表現で置き換え
html_text_mod = re.sub(r'<p class="b_price">([\d,]+)円</p>', rep, html_text)
# テキストを書き込み
html.write_text(html_text_mod)

この辺参考にしてください
pathlib
re

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/26 18:34

    ご回答ありがとうございます!(拝見するのが遅くて申し訳ありません)
    丁寧に流れや意味を説明して下さり、とてもわかりやすく勉強になります。

    早速、ご回答くださいました内容(0926.py)で実行してみたところ、下記のようなエラーが出てしまいました。自分なりに検索して調べてみたところ、まだ定義されていないローカル変数valueが使われている・・という意味なのかと思ったのですが、すみませんこの解決策がわかりません。
    再度ご教示いただければ大変ありがたいです。差し支えなければよろしくお願いいたします。

    Traceback (most recent call last):
    File "0926.py", line 25, in <module>
    html_text_mod = re.sub(r'<p class="b_price">([\d,]+)円</p>', rep, html_text)
    File "/Users/〜/.pyenv/versions/3.6.5/lib/python3.6/re.py", line 191, in sub
    return _compile(pattern, flags).sub(repl, string, count)
    File "0926.py", line 12, in rep
    value = math.ceil(value / TAX)
    UnboundLocalError: local variable 'value' referenced before assignment

    キャンセル

  • 2019/09/26 18:36

    すみません、一回回答書いたときに変数名書き換えたんですが一箇所書き換え忘れてました…
    修正します

    キャンセル

  • 2019/09/26 19:22

    早速ご回答下さいましてありがとうございます!!

    一度「NameError: name 'value_without_tax' is not defined」というエラーになってしまって、value_str = "{:,}".format(value_with_tax)に修正しましたところ
    無事書き換えができました!!

    replaceやreadlinesしか知らなかったところ、違う方法を知ることができてとても嬉しいです。
    本当に本当にありがとうございました。

    キャンセル

  • 2019/09/26 19:29

    何箇所もすみません…
    無事できたようで良かったです

    キャンセル

0

replaceの箇所をリスト内包表記で記述すればよいと思います。

[ l.replace(~) for l in lines_strip]

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/19 16:13

    ご回答ありがとうございます。
    price = [l.replace(columns_before, columns_after) for l in lines_strip]
    という様に修正してみたのですが、htmlファイルが変更されません。。

    キャンセル

0

beautifulsoupで文字書き換え

html = '''<!-- 商品一覧 -->
<div class="main">
    <div class="flex">
        <a href="item50.html"><img src="image/50.jpg"></a>
        <p class="b_name">商品50</p>    
        <p class="b_price">9,720円</p> <!-- 9,720円 → 9,000円+税 -->
    </div>

    <div class="flex">
        <a href="item60.html"><img src="image/60.jpg"></a>
        <p class="b_name">商品60</p>    
        <p class="b_price">8,640円</p><!-- 8,640円 → 8,000円+税 -->
    </div>

    <div class="flex">
        <a href="item62.html"><img src="image/62.jpg"></a>
        <p class="b_name">商品62</p>    
        <p class="b_price">7,560円</p><!-- 7,560円 → 7,000円+税 -->
    </div>

<!-- 以下続く -->

</div>'''

from bs4 import BeautifulSoup

# ファイルを開く
soup = BeautifulSoup(open('test.html', encoding='utf-8'), 'html.parser')

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

for i in soup.select("p.b_price"):
    place = int(i.get_text(strip=True).rstrip("円").replace(",", ""))
    i.string = "{:,}円+税".format(round(place / 1.08))

print(soup)

# 整形するならこちらで
# print(soup.prettify())

# ファイル保存
with open('test.html', mode = 'w', encoding = 'utf-8') as fw:
    fw.write(soup.prettify())
<!-- 商品一覧 -->
<div class="main">
<div class="flex">
<a href="item50.html"><img src="image/50.jpg"/></a>
<p class="b_name">商品50</p>
<p class="b_price">9,000円+税</p> <!-- 9,720円 → 9,000円+税 -->
</div>
<div class="flex">
<a href="item60.html"><img src="image/60.jpg"/></a>
<p class="b_name">商品60</p>
<p class="b_price">8,000円+税</p><!-- 8,640円 → 8,000円+税 -->
</div>
<div class="flex">
<a href="item62.html"><img src="image/62.jpg"/></a>
<p class="b_name">商品62</p>
<p class="b_price">7,000円+税</p><!-- 7,560円 → 7,000円+税 -->
</div>
<!-- 以下続く -->
</div>


書き換えははじめてやった

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/27 09:56

    誠に申し訳ありません。上記エラーは私のタイプミスによるものでした。
    無事書き換えできました。本当にありがとうございました!!

    キャンセル

  • 2019/09/27 17:16

    コメント忘れてましたが編集しました
    整形したくなければ
    fw.write(str(soup))
    に変更してください

    キャンセル

  • 2019/09/27 18:05

    編集してくださっていたのですね。
    気づかずすみません。ありがとうございます!
    fw.write(str(soup))も実行できまして、
    整形する方法としない方法、両方を知ることができました。
    ありがとうございました!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る