Python - Sqlite - Tratamento com 2 tabelas
Python - Sqlite - Tratamento com 2 tabelas | ||
Canal Qb |
A primeira tabela terá apenas uma coluna para armazenar o último valor da faixa gerada.
A segunda tabela conterá todas as consultas com suas respectivas respostas.
Aqui está o código modificado:
import asyncioimport aiohttpimport sqlite3from bs4 import BeautifulSoupasync def fetch(url):async with aiohttp.ClientSession() as session:async with session.get(url) as response:html = await response.text()soup = BeautifulSoup(html, 'html.parser')title = soup.find('title')if title and "Page Not Found" not in title.text:return f"{url.split('/')[-1]}: {title.text}"print(title.text)async def fetch_all(urls):responses = await asyncio.gather(*[fetch(url) for url in urls])return [r for r in responses if r]async def insert_last_value(conn, value):cursor = conn.cursor()cursor.execute("INSERT INTO last_value (value) VALUES (?)", (value,))conn.commit()async def get_last_value(conn):cursor = conn.cursor()cursor.execute("SELECT value FROM last_value ORDER BY ROWID DESC LIMIT 1")result = cursor.fetchone()return result[0] if result else Noneasync def insert_response(conn, value):cursor = conn.cursor()cursor.execute("INSERT INTO responses (value) VALUES (?)", (value,))conn.commit()async def main():try:db_conn = sqlite3.connect("urls.db")cursor = db_conn.cursor()cursor.execute('''CREATE TABLE IF NOT EXISTS last_value (value INTEGER)''')cursor.execute('''CREATE TABLE IF NOT EXISTS responses (value TEXT UNIQUE)''')last_value = await get_last_value(db_conn)if not last_value:last_value = 0end_value = int(input("Digite o valor final: "))urls = [f'https://pt.aliexpress.com/item/{i}.html' for i in range(last_value + 1, end_value + 1)]responses = await fetch_all(urls)for response in responses:if response:value = response.split(':')[0]try:await insert_response(db_conn, value)print(f"Valor {value} inserido na tabela de respostas")except sqlite3.IntegrityError:print(f"Valor {value} já existe na tabela de respostas")await insert_last_value(db_conn, end_value)print(f"Último valor da faixa ({end_value}) inserido na tabela de último valor")except RuntimeError:passfinally:db_conn.close()loop = asyncio.get_event_loop()loop.run_until_complete(main())
O código modificado tem quatro funções de banco de dados:
insert_last_value(): insere o último valor da faixa gerada na tabela last_value.
get_last_value(): retorna o último valor da tabela last_value.
insert_response(): insere uma consulta e sua resposta na tabela responses.
main(): obtém o último valor da tabela last_value, gera uma nova faixa de URLs, faz as consultas e insere os resultados na tabela responses. Em seguida, o último valor da faixa gerada é inserido na tabela last_value.
Com estas modificações, você pode executar o script várias vezes, e ele começará a gerar uma nova faixa de URLs a partir do último valor inserido na tabela
--**--
Possíveis erros:
O erro "AttributeError: 'NoneType' object has no attribute 'text'" ocorre porque a variável "title" está sendo definida como "None" em algumas páginas e, portanto, não possui o atributo "text".
Para corrigir esse erro, você pode adicionar uma verificação para garantir que a variável "title" não seja "None" antes de tentar acessar o atributo "text". Por exemplo:
async def fetch(url):async with aiohttp.ClientSession() as session:async with session.get(url) as response:html = await response.text()soup = BeautifulSoup(html, 'html.parser')title = soup.find('title')if title and "Page Not Found" not in title.text:return f"{url.split('/')[-1]}: {title.text}"elif title:print(title.text)else:
print(f"Não foi possível encontrar o título da página: {url}")
Dessa forma, se a variável "title" for "None", será impressa uma mensagem indicando que não foi possível encontrar o título da página.
--**--
Para atualizar a linha existente na tabela "last_value" em vez de criar uma nova linha toda vez que o script é executado, você pode modificar a função "main" da seguinte forma:
async def main():try:db_conn = sqlite3.connect("urls.db")cursor = db_conn.cursor()cursor.execute('''CREATE TABLE IF NOT EXISTS last_value (value INTEGER)''')cursor.execute("SELECT value FROM last_value")row = cursor.fetchone()if row is None:last_value = 0else:last_value = row[0]end_value = int(input("Digite o valor final: "))urls = [f'https://pt.aliexpress.com/item/{i}.html' for i in range(last_value + 1, end_value + 1)]responses = await fetch_all(urls)for response in responses:if response:value = response.split(':')[0]try:await insert_into_db(db_conn, value)print(f"Valor {value} inserido no banco de dados")except sqlite3.IntegrityError:print(f"Valor {value} já existe no banco de dados")cursor.execute("REPLACE INTO last_value (value) VALUES (?)", (end_value,))db_conn.commit()except RuntimeError:passfinally:db_conn.close()
Essa modificação primeiro verifica se existe uma linha na tabela "last_value" e, em seguida, define o valor inicial para a geração de URLs com base no valor existente na tabela. Depois de gerar as URLs e inserir as respostas na tabela "urls", a função atualiza o valor existente na tabela "last_value" usando a cláusula "REPLACE INTO", que substitui a linha existente se ela já existe ou insere uma nova linha se ainda não existe.
--**--
o código e parece que acidentalmente excluí a função insert_into_db. Para corrigir o erro, basta adicionar novamente a definição da função insert_into_db ao código, como mostrado abaixo:
import asyncioimport aiohttpimport sqlite3from bs4 import BeautifulSoupasync def fetch(url):async with aiohttp.ClientSession() as session:async with session.get(url) as response:html = await response.text()soup = BeautifulSoup(html, 'html.parser')title = soup.find('title')if title and "Page Not Found" not in title.text:return f"{url.split('/')[-1]}: {title.text}"print(title.text)async def fetch_all(urls):responses = await asyncio.gather(*[fetch(url) for url in urls])return [r for r in responses if r]async def insert_into_db(conn, table_name, value):cursor = conn.cursor()cursor.execute(f"INSERT INTO {table_name} (value) VALUES (?)", (value,))conn.commit()async def main():try:db_conn = sqlite3.connect("urls.db")cursor = db_conn.cursor()cursor.execute('''CREATE TABLE IF NOT EXISTS last_value (value INTEGER)''')cursor.execute('''CREATE TABLE IF NOT EXISTS urls (value TEXT UNIQUE)''')cursor.execute("SELECT value FROM last_value")row = cursor.fetchone()if row:last_value = row[0]else:last_value = 0end_value = int(input("Digite o valor final: "))urls = [f'https://pt.aliexpress.com/item/{i}.html' for i in range(last_value + 1, end_value + 1)]responses = await fetch_all(urls)for response in responses:if response:value = response.split(':')[0]try:await insert_into_db(db_conn, 'urls', value)print(f"Valor {value} inserido na tabela urls")except sqlite3.IntegrityError:print(f"Valor {value} já existe na tabela urls")cursor.execute("REPLACE INTO last_value (value) VALUES (?)", (end_value,))db_conn.commit()print(f"Último valor inserido na tabela last_value: {end_value}")except RuntimeError:passfinally:db_conn.close()loop = asyncio.get_event_loop()loop.run_until_complete(main())
Com essas mudanças, o script agora deve funcionar corretamente. Verifique se o erro foi resolvido.
--**--
Para informar o título na mensagem de impressão, você pode alterar a função insert_into_db() para receber dois parâmetros: value e title. Em seguida, você pode atualizar a mensagem de impressão para exibir o valor e o título. Veja o código abaixo com as alterações necessárias:
async def insert_into_db(conn, value, title):cursor = conn.cursor()cursor.execute("INSERT INTO urls (value, title) VALUES (?, ?)", (value, title))conn.commit()# ...for response in responses:if response:value, title = response.split(':')try:await insert_into_db(db_conn, value, title.strip())print(f"Valor {value} com título '{title.strip()}' inserido na tabela urls")except sqlite3.IntegrityError:
print(f"Valor {value} já existe na tabela urls")
Isso deve imprimir uma mensagem informando o título junto com o valor que foi inserido na tabela.
--**--
se você quiser manter apenas o valor na tabela urls e exibir o título apenas no print, você pode fazer a seguinte modificação:
async def insert_into_db(conn, value):cursor = conn.cursor()cursor.execute("INSERT INTO urls (value) VALUES (?)", (value,))conn.commit()# ...for response in responses:if response:value, title = response.split(':')try:await insert_into_db(db_conn, value)print(f"Valor {value} com título '{title.strip()}' inserido na tabela urls")except sqlite3.IntegrityError:print(f"Valor {value} já existe na tabela urls")
Isso deve imprimir uma mensagem com o título e inserir apenas o valor na tabela urls.
Nenhum comentário
Comente só assim vamos crescer juntos!
Observação: somente um membro deste blog pode postar um comentário.