@binks (binks)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

python

Q&A

Closed

解決したいこと

位置によって辞書の結果が変わってしまいます。
辞書を統合したときにsize_dictの内容が変わります。
どのように修正すればよいのでしょうか。

プログラミング初学にてpythonを勉強中です。
私が運営するサイトからスクレイピングの練習をしております。
よろしくお願い致します。

発生している問題

print(size_dict)の結果
{'サイズ': '0.05 x 30mm x 500m'}
{'サイズ': '0.05 x 40mm x 500m'}
{'サイズ': '0.05 x 50mm x 500m'}
  中略
{'サイズ': '0.1 x 600mm x 200m'}

print(pori_data)の結果
{'サイズ': '0.1 x 600mm x 200m', '税込価格': '2,640円'}
{'サイズ': '0.1 x 600mm x 200m', '税込価格': '3,410円'}
{'サイズ': '0.1 x 600mm x 200m', '税込価格': '3,740円'}
  中略
{'サイズ': '0.1 x 600mm x 200m', '税込価格': '23,100円'}
         ↑
(サイズ)がすべて同じ結果になってしまいます。

該当するソースコード

from bs4 import BeautifulSoup
import urllib.request as req
import re

url = "https://略"
res = req.urlopen(url)
soup = BeautifulSoup(res, "html.parser")

size_li = soup.select("body > center > table > tbody > tr:nth-child(4) > td:nth-child(2) > table > tbody > tr:nth-child(3) > td > table:nth-child(12) > tbody > tr:nth-child(n+6):nth-child(-n+22) > td:nth-child(1)")

for size in size_li:
    size_text = size.text
    size_text_n = size_text.replace('\n', '')

    target = '0'
    idx =size_text_n.find(target)
    size_s = size_text_n[idx:]

    target = 'm'
    idx = size_s.rfind(target)
    size_list = size_s[:idx+1].strip()

    size_dict = {"サイズ": size_list}
    print(size_dict)

price_li = soup.select("body > center > table > tbody > tr:nth-child(4) > td:nth-child(2) > table > tbody > tr:nth-child(3) > td > table:nth-child(12) > tbody > tr:nth-child(n+6):nth-child(-n+22) > td:nth-child(3)")

for price in price_li:
    price_text = price.text
    price_text_n = price_text.replace('\n', '')

    target = '円'
    idx = price_text_n.rfind(target)
    price_list = price_text_n[:idx+1].strip()

    price_dict = {"税込価格": price_list}

    pori_data = {**size_dict, **price_dict}
    print(pori_data)
0 likes

1Answer

size_dict = {"サイズ": size_list} で最後の size_list だけが size_dict の "サイズ" に残ります。
その次のfor文で最後の size_list だけを使うので全て同じ "サイズ" になりますよ。

単純な例
size_li = [
    '0.1 x 600mm x 200m',
    '0.1 x 600mm x 200m',
    '0.1 x 600mm x 200m',
    '0.1 x 600mm x 200m',
]

for size in size_li:
    size_dict = {"サイズ": size}

print(size_dict)
実行結果
{'サイズ': '0.1 x 600mm x 200m'}

どのようなデータになって欲しいのか、具体的な例を書いていただけますか?

想像するに、サイズと価格の対応リストを作りたいのでしょうか?
それならば、以下のようにzipを使って対応させるのがいい気がします。

from bs4 import BeautifulSoup
import urllib.request as req
import re


def convert_size(text):
    begin = text.find('0')
    end = text.rfind('m')
    return {"サイズ": text[begin:end+1].replace('\n', '')}


def convert_price(text):
    end = text.rfind('円')
    return {"税込み価格": text[:end+1].strip().replace('\n', '')}


url = "https://略"
res = req.urlopen(url)
soup = BeautifulSoup(res, "html.parser")
sizes = soup.select("body > center > table > tbody > tr:nth-child(4) > td:nth-child(2) > table > tbody > tr:nth-child(3) > td > table:nth-child(12) > tbody > tr:nth-child(n+6):nth-child(-n+22) > td:nth-child(1)")
prices = soup.select("body > center > table > tbody > tr:nth-child(4) > td:nth-child(2) > table > tbody > tr:nth-child(3) > td > table:nth-child(12) > tbody > tr:nth-child(n+6):nth-child(-n+22) > td:nth-child(3)")
pori_data = [{**convert_size(size.text), **convert_price(price.text)}
             for size, price in zip(sizes, prices)]
print(pori_data)
1Like

Comments

  1. @binks

    Questioner

    完全に求めていたものです。
    ありがとうございます。

Your answer might help someone💌