최근 버전에서 Python의 문자열 포맷터 변경으로 인해 MySQL 커넥터가 손상 되었습니까?
Twitter API에서 트윗을 얻기 위해 간단한 스크립트를 작성하고 있거나 간단해야합니다. (저는 개발자 / 앱 키가 있고 스크래핑이나 그런 종류의 것이 아닌 Tweepy 인터페이스를 사용하고 있습니다. 더 가까운 것을 위해 Tweepy를 버릴 수 있습니다. 최신 API이지만 여기에서이 문제를 일으키는 것은 거의 확실하지 않습니다.)
필연적으로 많은 특수 문자가있는 트윗을 삽입 할 때까지 연결하고 쿼리 할 수있는 MySQL 인스턴스가 있습니다. 명확하게 말하자면 MySQL 용 공식 Python 드라이버 / 커넥터를 사용하고 있습니다.
import mysql.connector
from mysql.connector import errorcode
이제 StackOverflow가 사람들이 내 정확한 오류를 얻는 스레드로 흩어져 있음을 알고 있습니다. 단순히 MySQL 구문 설명서를 확인하라고 말합니다. 이 스레드는 그렇게 오래되지 않았습니다 (그리고 최신 Python을 사용하지 않고 일부 NLP 라이브러리와의 호환성을 위해 3.7.9를 사용합니다) 대답은 특수 문자가있는 문자열을 이전에 배치하는 것입니다. 스타일 형식 문자열 WITHIN cursor.execute 메서드, 문자열 변수 자리 표시자를 따옴표로 묶고 빈 두 번째 값이있는 튜플을 전달하려면 내 경우와 같이 하나의 변수 만 삽입해야합니다. 이것은 또한 MySQL 웹 사이트에 버그 보고서 응답의 일부로 게시 된 솔루션이지만 아직 성공하지 못했습니다.
여기에 내가 가진 것이 있습니다-여기 수십 페이지의 지침과 공식 데이터베이스 웹 사이트를 따르십시오.
for tweet in tweepy.Cursor(twilek.search, q=keyword, tweet_mode='extended').items():
twi_tweet = tweet.full_text
print(twi_tweet)
twi_tweet = twi_tweet.encode('utf8')
requests_total+=1
os.environ['TWITTER_REQUESTS'] = str(requests_total)
requests_total = int(os.environ.get('TWITTER_REQUESTS'))
# insert the archived tweet text into the database table
sql = 'USE hate_tweets'
ms_cur.execute(sql)
twi_tweet = str(twi_tweet)
insert_tweet = re.sub(r'[^A-Za-z0-9 ]+', '', twi_tweet)
ms_cur.execute("INSERT INTO tweets_lgbt (text) VALUES %s" % (insert_tweet,))
cnx.commit()
print(ms_cur.rowcount, "record inserted.")
(twilek은 내가 dork이기 때문에 커서 객체입니다)
예상 결과 : 문자열 포맷터가 처리하고 tweets_lgbt 테이블에 행으로 추가 할 수있는 수정 된 트윗 문자열을 MySQL에 전달합니다.
실제 결과 : 모든 트윗에 대한 구문 오류로 인해 삽입이 실패합니다.
나는 정규식을 사용하여 영숫자와 공백을 제외한 모든 것을 제거하려고 시도했습니다. 현재 Python 버전의 새로운 문자열 형식 기능이이 커넥터와의 호환성이 깨 졌는지 궁금합니다. 공식 드라이버를 사용하는 것을 선호하지만 필요한 경우 ORM으로 전환합니다. (F 문자열과 같은 최신 기능을 사용해 보았는데 동일한 결과가 발생한다는 것을 알았습니다.)
답변
이것은 테이블에 행을 삽입하는 방법입니다.
insert_tweet = "ABCEFg 9 XYZ"
"INSERT INTO tweets_lgbt (text) VALUES ('%s');"%(insert_tweet)
"INSERT INTO tweets_lgbt (text) VALUES ('ABCEFg 9 XYZ');"
참고할 사항
문자열 포맷터에 대한 인수는 함수에 대한 인수와 같습니다. 따라서 끝에 쉼표를 추가하여 문자열을 튜플로 변환 할 수 없습니다.
한 번에 여러 값을 삽입하려는 경우 cursor.executemany 또는 this answer를 사용할 수 있습니다 .
다음과 같은 관찰이 있습니다.
VALUES
절은 필요 괄호VALUES (%s)
- 인용 부호 표시가 / 값으로 탈출하여 커서의 위임되어야
execute
는 SQL에서 인용되지 않은 표시자를 사용하고, 두 번째 인수로 값을 전달하여, 방법cursor.execute(sql, (tweet_text,))
또는cursor.executemany(sql, [(tweet_text1,), (tweet_text2,)])
- 이 단계가 적용되면 인코딩 / 스트링 파잉 / 정규화 할 필요가 없습니다.
twi_text
astr
이고 데이터베이스의 문자셋 / 콜 레이션이 전체 UTF-8 범위 (예 : utf8mb4)를 지원 한다고 가정 하면 삽입이 성공합니다.- 특히, 인코딩 한
str
다음str
결과 를 호출 하는 것은 피해야합니다."b'my original string'"
- 특히, 인코딩 한
이 질문의 코드 수정 버전은 저에게 효과적입니다.
import mysql.connector
DDL1 = """DROP TABLE IF EXISTS tweets_lgbt"""
DDL2 = """\
CREATE TABLE tweets_lgbt (
`text` VARCHAR (256))
"""
# From https://twitter.com/AlisonMitchell/status/1332567013701500928?s=20
insert_tweet = """\
Particularly pleased to see @SarahStylesAU
quoted in this piece for the work she did
👌
Thrive like a girl: Why women's cricket in Australia is setting the standard
"""
# Older connector releases don't support with...
with mysql.connector.connect(database='test') as cnx:
with cnx.cursor() as ms_cur:
ms_cur.execute(DDL1)
ms_cur.execute(DDL2)
ms_cur.execute("INSERT INTO tweets_lgbt (`text`) VALUES (%s)", (insert_tweet,))
cnx.commit()
print(ms_cur.rowcount, "record inserted.")