Python кодировка UTF8 и MySQL

в разделе Программирование | Метки: Python, MySQL

Многочасовые пляски с бубном наконец то привели к желаемому результату и в базу все пишется в нормальной кодировке. Проблема оказалась в том что в самой MySQL была по умолчанию кодировка latin1 а не utf-8

вот так вот все это проявлялось:

$ python yelp.py 
восточного ао управа района богородское 
yelp.py:148: Warning: Incorrect string value: '\xD0\xB2\xD0\xBE\xD1\x81...' for column 'name' at row 1   
 
  cursor.execute("""INSERT INTO grab_moscow (name) VALUES(%s)""",(title))

посмотреть какая сейчас кодировка в MySQL можно этим запросом:

SHOW VARIABLES LIKE 'char%';

я создавал базу с помощью MySQL Query Browser, а правильнее было бы создавать запросом типа этого

CREATE DATABASE db CHARACTER SET utf8 COLLATE utf8_general_ci;

При использовании модуля MySQLdb в python необходимо указать следующее:

 conn = MySQLdb.connect(host = "localhost",
user = "root",
passwd = "secretpassword",
db = "yp",
use_unicode = 1,
charset = 'utf8'
 
)
conn.set_character_set('utf8')
cursor = conn.cursor()
cursor.execute('SET NAMES utf8')
cursor.execute('SET CHARACTER SET utf8')
 
cursor.execute('SET character_set_connection=utf8')

Куски из кода - грабер сайта "Желтые страницы", в ходе написания в очередной раз на практике убедился в том что чем проще решение тем оно лучше. По сути это и является принципом большинства Unix систем, множество маленьких программ, которые хорошо и безглючно работают. Год или 1.5 года назад, когда я только начал более менее серьезно заниматься веб-программированием я делал сайт под партнерку mp3sugar.com. Нужно было сделать какой то сайт, чтобы было чего показывать на собеседованиях, а для этого все работодатели требовали рабочие интернет-проекты и свой код.

Тогда я начал с нуля писать движок для сайта под эту партнерку, написание самого движка много времени не заняло. Потом я решил сграбить сайт с текстами песен, выдернуть из него все тексты и объеденить все это с сахарной базой. Сначала для скачивания сайта я натравил Teleport Pro (полную версию), он работал всю ночь, а на утро я обнаружил что он скачал что-то типа 64000 страниц и больше он не может. Ограничение такое в программе хотя она и платная. Потом скачал бесплатный Httrack, он таки все нормально выкачал.

Сейчас нарыл на винте те регулярные выражения которыми все парсилось, тогда я только учился их писать и вообще не знал, так что вот пример как их писать НЕ надо :)

result_urls = re.findall(r'/search/\?s=.*(?=")', text) 
result_artists = re.findall(r'(?!/search/\?s=.*".*class=st&gt;.*)(?&lt; =class=st&gt;).*(?&lt; =[^])(?&lt; =[^\[\?\] <a HREF="/browse/A/P2.html"><strong>»</strong></a>\s\s\s)', text)   
 
result_songs  = re.findall(r'(?!/search/\?s=.*".*class=st&gt;.*)(?&lt; =class=st&gt;).*(?&lt; =[^])(?&lt; =[^\[\?\]Текст.*песни)(?&lt; =Текст.песни).*(?&lt; =[^])

Скачанный сайт на жестком диске занимал что-то около 8 гигов, и все это парсилось и запихивалось в базу наверно часа 2-3. Чуть ниже пример эволюции в написании граберов :) 15000 данных о фирмах скачались минут за 20, это при том что я специально выставил задержку в 5 секунд после каждой страницы чтобы меня не забанили на файрволе как злобного dos-атакера.

  regexp = { 'items' : r"""<a CLASS="comp_header" HREF="(.*)">(.*)</a>""", 
             'pages' : r"""
<td><a HREF="(.*)"><img TITLE="на 1 страницу вперед" ALT="на 1 страницу вперед" BORDER="0" HEIGHT="9" WIDTH="5" SRC="http:\/\/img.ypages.ru\/pager\/forward_1_on.gif" />&lt; \/a&gt;</a></td>
""", 
             #'pages' : r""" <a CLASS="apage" HREF="(.+)">""", 
             'item_d_title' : r""" 
</a>  
 
Почтовый адрес (.+):  
 
""", 
             'item_d_address' : r""" 
<a TARGET="_blank" HREF="http://www.postindex.ru/(.+)">(.+)</a>,  (.+?)(<span CLASS="noprint|&lt;/div">
 
)""", 
             'item_d_telephone' : r""" 
</span>т (.+)  
 
""", 
             'item_d_website' : r"""  
 
<a TARGET="_blank" HREF="(.+)">""", 
             'item_d_metro' : r"""
<p CLASS="c-info"><img VSPACE="1" HSPACE="1" STYLE="background-color: #0077ce" ALT="(.+)" SRC="http:\/\/img.ypages.ru\/metro\/metrologo.gif" />  (.+),""", 
             'item_d_postcode' : r"""
 
</p><p CLASS="c-info"><a TARGET="_blank" HREF="(.+)">(.+)</a>,""", 
           } 
  regexp_group = { 'items' : 1, 
                   'pages' : 1, 
                   'item_d_title' : 1, 
                   'item_d_address' : 3, 
                   'item_d_telephone' : 1, 
                   'item_d_website' : 1, 
                   'item_d_metro' : 2, 
                   'item_d_postcode' : 2 
                 }

Я пишу все это не к тому чтобы показать какой я типа умный, а к тому что упрощение намного ускоряет решение задач, и зачастую все то что проще сделано работает надежнее и быстрее. Сначала я хотел дергать страницу, загружать ее как XML документ, находить нужную ветку и оттуда брать то что надо. К счастью для меня наверно, html-код страницы был настолько криво написан что tidy его даже не смог сделать нормальным, и dom парсер не смог его загрузить, тогла я плюнул и за несколько минут написал эти регулярные выражения, в чем очень помогает бесплатная утилитка kodos (под виндой тоже работает).