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§ion=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 шт):
Ошибка 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
По данным, которые вы прислали становится все ясно.
Как поймать несастыковку? Я запросил данные и обратился к ключам, которые содержит словарь
>>> import requests
>>> import json
>>> url = 'https://www.mechta.kz/api/new/catalog?properties=&page=2§ion=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 и отформатируйте. Вы увидите структуру ключей.
Пример

