Error: string indices must be integers

введите сюда описание изображения

from PyQt5.Qt import *
from pickle import TRUE
import requests
from bs4 import BeautifulSoup



class ThreadM(QThread):
    stepChanged = pyqtSignal(int, int)
    finished = pyqtSignal(list)
    error = pyqtSignal(str)

    def __init__(self, url, file, HEADERS):
        super().__init__()
        self.url = url
        self.file = file
        self.HEADERS = HEADERS


    def run(self):        
        self.parseM()
        
    def parseM(self):

        html = self.get_html()
        if not html:
            if html != False:
                self.error.emit(
                    f'Error: status_code={html.status_code}'
                )
            return
        
        if html.status_code == 200:
            products = []
            pages_count = self.get_pages_count(html.text)
            for page in range(1, pages_count + 1):
                self.stepChanged.emit(page, pages_count)
                
                html = self.get_html(params={'page': page})
                products.extend(self.get_content(html.text))
                self.msleep(50)
                
            self.finished.emit(products)

        else: 
            self.error.emit(f'Error: status_code={html.status_code}')

    def get_html(self, params=None):
        try:
            r = requests.get(self.url, headers=self.HEADERS, params=params)
            return r 
        except:
            self.error.emit(f'Error: Что-то пошло не так.')
            return False

    def get_pages_count(self, html):
        soup = BeautifulSoup(html, 'html.parser')
        pagination = soup.select('span.block')
        if pagination:
            return int(pagination[-1].get_text().replace('\n', ''))
        else:
            return 1

    def get_content(self, html):
        items = requests.get(url).json()
        url = 'https://www.mechta.kz/api/new/catalog?properties=&page=2&section=smartfony'
        products = []
        for item in items:
            price = item['price']
            old_price = item['base_price']
            products.append({
                'title': item['name'],
                'price': price,
                'old price': old_price
            })    
        return products

Ответы (2 шт):

Автор решения: MaxU - stop genocide of UA

Ошибка TypeError: string indices must be integers возникает в том случае когда вы пытаетесь указать не целочисленное значение при попытке доступа к элементам строки. Например использовав строку / вещественное число / дату / другой объект в качестве индекса:

Воспроизведение ошибки:

s = "123"

s["a"]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-154-70b97906f129> in <module>
----> 1 s["a"]

TypeError: string indices must be integers

Ошибка говорит о том что значением индекса при обращении к элементам строки должно быть целое число. Ту же ошибку мы получим при попытке использовать вещественное число в качестве индекса:

print(s[3.14])
# TypeError: string indices must be integers

В качестве индекса нужно указывать целое число.

print(s[1])
# 2

Похожую ошибку (TypeError: slice indices must be integers or None or have an __index__ method) можно получить при попытке использования строки в срезе:

print(s["a":])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-160-0c849cd778d0> in <module>
----> 1 print(s["a":])

TypeError: slice indices must be integers or None or have an __index__ method

Суть - та же. Используйте целые числа для указания границ среза.


Другая ошибка из того же семейства: (TypeError: list indices must be integers or slices, not str) - попытка использовать строковой индекс при обращении к списку или кортежу:

lst = [1,2,3]
idx = "0"
print(lst[idx])

выдаст:

TypeError: list indices must be integers or slices, not str

то же самое с кортежем - TypeError: tuple indices must be integers or slices, not str:

tpl = (1,2,3)
idx = "0"
print(lst[idx])

выдаст:

TypeError: tuple indices must be integers or slices, not str
→ Ссылка
Автор решения: Dmitry

По данным, которые вы прислали становится все ясно.

Как поймать несастыковку? Я запросил данные и обратился к ключам, которые содержит словарь

>>> import requests
>>> import json
>>> url = 'https://www.mechta.kz/api/new/catalog?properties=&page=2&section=smartfony'
>>> items = requests.get(url).json()
>>> items.keys()
dict_keys(['result', 'errors', 'data'])

То есть когда вы пишете цикл по items вы перебираете значения по этим трем ключам. Что скорей всего логически не верно.

Вам нужны данные в ключе data, а далее в items:

for item in items["data"]["items"]:
  """логика здесь"""

Попробуем забрать имена

>>> for item in items["data"]["items"]:
...   print(item["name"]) 
...
Телефон сотовый APPLE iPhone 12 PRO 128GB (Graphite)
Телефон сотовый APPLE iPhone 13 Pro 1TB Gold
Телефон сотовый SAMSUNG SM A 525 Galaxy A52 256 GB FZKIS (Black)
Телефон сотовый APPLE iPhone 13 mini 128GB Pink
Телефон сотовый XIAOMI Redmi Note 10S 6/128GB Ocean Blue

, цены

>>> for item in items["data"]["items"]:
...   print(item["price"]) 
... 
589890
949990
209890
409990
119990
89990

И еще один момент, определение url идет после вызова requests.get(). Вы так и задумывали?

base_prices доступны по ключу - item["prices"]["base_price"]

Для того, чтобы понять как и что сохраните у себя на компе json-файл. Откройте его, например в VSCode и отформатируйте. Вы увидите структуру ключей.

Пример

введите сюда описание изображения

→ Ссылка