Site do Leonardo Priori

Fazendo Importações Usando Expressões Regulares

Importei o meu blog do blogspot para o meu servidor em o uso de wordpress ou outra ferramenta do tipo. Não é muito complicado. Acho que farei mais posts sobre o assunto, mas neste eu só queria mostrar este código.

<?
$post_count = isset($_GET['count'])?$_GET['count']:0;

$r = $db->query("SELECT count(*) as count FROM post_link");
$post_len = $r->fetch();
$post_len = $post_len['count']-1;

$r = $db->query("SELECT * FROM post_link ORDER BY id DESC LIMIT $post_count,1");
$r = $r->fetch();
$client = new Zend_Http_Client($r["url"], array('timeout' => 30));
$link_id = $r["id"];

$response = $client->request();
$response = $response->getBody();

// usa expressões regulares para localizar as informações
$post = array();
preg_match("/<div class='post hentry.*?>(.*)<div class=[\"']comments/ms", $response, $post);
$post = $post[1];

$title = array();
preg_match("/<h3 class='post-title entry-title'>(.*)<\\/h3>/ms", $post, $title);
$title = trim( strip_tags($title[1]) );

$content = array();
preg_match("/<div class='post-body entry-content'>(.*?)".
		"<div style='clear: both;'>/ms", $post, $content);
$content = trim( $content[1] );

$published = array();
preg_match("/<abbr class='published' title='(.*?)'>/ms", $post, $published);
$published = trim($published[1]);

// salva no banco de dados o post
$r = $db->add('blog_post',array(
	'title'              => $title,
	'content'            => $content,
	'link_id'            => $link_id,
	'original_published' => $published,
	'published'          => strtotime($published),
	'published_offset'   => date("Z",strtotime($published))
));
$post_id = $db->insert_id();

$comments = explode("<dt class='comment-author",$response);
array_shift($comments);
foreach( $comments as $v ){
	
	// usa expressões regulares para localizar as informações
	$comment = array();
	preg_match( "/<\\/a>(.*?)\\s*disse....*?<\\/dt>.*?<dd class='comment-".
			"body'>.*?<p>(.*?)<\\/p>.*?title='comment permalink'>(.*?)</ms",
		$v, $comment
	);
	array_shift( $comment);

	$author = trim($comment[0]);
	$a = array();
	preg_match(
		"/<[^>]*href='([^']*?)'[^>]*>/ms",
		$author, $a
	);
	$author_url = $a[1]?$a[1]:'';
	$author = trim(strip_tags($author));

	$comment_content = trim($comment[1]);
	$comment_time = trim($comment[2]);

	// salva no banco de dados o comentário
	$db->add('blog_comment',array(
		'url' => $author_url,
		'content' => $comment_content,
		'post_id' => $post_id,
		'author' => $author,
		'author_url' => $author_url,
		'original_inserted' => $comment_time,
		'inserted' => strtotime($comment_time)?strtotime($comment_time):0,
		'inserted_offset' => date("Z",strtotime($comment_time))?
			date("Z",strtotime($comment_time)):0
	));
}
?>

preg_match faz uma busca no texto usando a expressão regular e colocar os pedaços do que foi encontrado em um array. O que bater com expressão regular toda será colocado na posição 0 do array, o que estiver entre os primeiros parênteses e for localizado de acordo com a expressão regular inteira vai ser colocado na segunda posição (posição 1), a segunda dupla de parênteses na posição 2 e assim por diante. $db->add é uma funçãozinha minha que uso a muito tempo, muitas bibliotecas php tem funções similares, nela você manda o nome da tabela e as entradas em um array com chaves indicando o campo da tabela, com esses atributos a método insere uma entrada no banco de dados.

comentários (8) publicado quinta, 02 abril de 2009 às 17:29

juicydrop

Se você estiver usando Firefox 3+ ou Chrome, dê uma olhada nisso www.nihilogic.dk/labs/juicydrop.

comentários (0) publicado quarta, 25 março de 2009 às 09:49

O DOM é uma bagunça

O DOM é uma bagunça (The DOM IS A Mess) é uma ótima palestra do John Resing, criador do jquery. Primeiro ele fala sobre alguns bugs.

No getElementById o ie confunde id com name, e quando trabalha com XML tem algumas particularidades. No getElementsByTagName no ie 5.5 o "*" não funciona, o ie 7 troca alguns índices do array pelo ids dos elementos, colocando um elemento de id "length", por exemplo, no lugar do length do array. No getElementByClassName do Opera 9.6 ele só checa a primeira classe do elemento, se o elemento ter class=”a b” por exemplo, se você procurar por elementos com classe ”b” aquele não estará no retorno. querySelectorAll não funciona no ie 8 no quirks mode, no safári 3.1 temos problemas de memória, e o safári 3.2 não aceita queries com letras maiúsculas. E depois ele fala sobre algumas soluções e sobre o jquery.


John Resig: "The DOM Is a Mess" @ Yahoo! Video

E o DOM realmente é uma bagunça, sem dúvida. Eu a muito tempo tenho vontade de fazer uma framework para javascript. Mas concorrer contra jquery é foda. Muitos frameworks utilizam de códigos dele e eu iria ter que usar vários dos códigos dele. O que mais me deixa grilado é decidir o nome dos métodos e como utilizá-los. Pensei em muitas coisas.

Usar addClickListener( func ), addListener( "click", func ), addEvent( "click", func ), addEventListener( element, "click", func ). E para o setAttribute? Usar setAttr ou usar simplesmente set? Acho que vou ficar com os nomes originais, somente vou concertar os bugs, implementar o querySelectorAll e uma biblioteca para animações.

comentários (0) publicado terça, 17 março de 2009 às 07:48

Título e RSS

O site precisava de título e rodapé, claro. Coloquei essas duas coisas e uma bolinha separando um post do outro. Acho que ficou bem melhor. Estou planejando fazer um texto sobre codificação (Unicode, ISO-8859-1, etc) e um outro sobre datas (UTC, GMT, timestamp, era UNIX, etc). Vou aproveitar que tenho que criar um sistema para enviar e editar posts pelo site vou implementar sessões usando banco de dados e um log de acessos. Mas agora acho que vou para o bar! Ah, o site também tem agora suporte a feed, fiz um pequeno script php que cria um no formato rss.

<?
	include 'include.php';
	$entries = mysql_query('
		SELECT post.* FROM post
		ORDER BY published_at DESC
	');
	
	$charset = mysql_client_encoding(); // latin1
	if( ereg('^latin.$',$charset) ){
		$charset = 'ISO-8859-'.substr($charset, -1);
	}
	// header( 'Content-Type: application/rss+xml;  charset=ISO-8859-1' );
	header('Content-Type: txt/xml; charset='.$charset);
	
	function xmlscape( $str ){
		if( strlen($str) < 200 or ereg(']]>',$str) )
			return htmlspecialchars( $str );
		else
			return "<![CDATA[$str]]>";
	}
	function xmlsdate( $time ){
		// Tue, 03 Jun 2003 09:39:21 GMT
		return  gmdate("D, d M Y H:i:s", $time ).' GMT';
	}
	
	echo '<?xml version="1.0" encoding="'.$charset.'"?>';
?>
<rss version="2.0">

  <channel>
    <title>Site do Leonardo Priori</title>
    <link>http://www.leonardopriori.com/</link>
    <description></description>

    <language>pt-br</language>
	<? while( $entry = mysql_fetch_assoc($entries) ): ?>
    <item>
      <title><?=htmlspecialchars($entry['title'])?></title>
      <description><?=xmlscape($entry['content'])?></description>

      <pubDate><?=xmlsdate($entry['published_at'])?></pubDate>
      <link>http://www.leonardporiori.com/?post=<?=$entry['id']?></link>
      <guid>http://www.leonardporiori.com/?post=<?=$entry['id']?></guid>

      <comments>http://www.leonardporiori.com/?post=<?=$entry['id']?>#comments</comments>
    </item>
	<? endwhile; ?>
  </channel>
</rss>
comentários (0) publicado sexta, 13 março de 2009 às 23:14

Gimp

Li no Meio Bit uma notícia de algo que já sabia, mas gostei de ouvir de novo. Photoshop é muito melhor que Gimp. Uma das maiores bobagens que ouvimos dos fãs do Linux é sobre o Gimp. Editores de imagens existem aos montes, temos muitos do nível do Gimp, mas Photoshop é Photoshop. O "site Extremetech fez uma profunda pesquisa comparando o desempenho do Photoshop CS4 em quatro máquinas". A notícia só fala sobre o desempenho, mas claro que o Gimp é pior em vários aspectos. Tanto a interface do programa, quanto o alcance e a qualidade de suas ferramentas são bastante inferiores.

comentários (0) publicado sexta, 13 março de 2009 às 03:14

Mais

Agora adicionei mais um treco! Este programa em javascript que colore os códigos automaticamente. É o highlight.js. Por enquanto eu vou deixar ele assim, mas estou pensando em colocar para ele só estilizar o código quando eu estiver editando o código, de forma que ele não precise ser executado pelo cliente toda vez que página é carregada.

comentários (0) publicado quinta, 12 março de 2009 às 09:22

Duas tabelas

Para os comentários usei comment e os campos id, content, author_url, author_name, author_email, created_at (int) e post_id. Para os posts eu não sei.

rss usa "item" para os posts, atom usa "entry". Mas esses padrões não são específicos para blogs, usarei post mesmo, me parece o mais direto. Os campos serão id, content, title, created_at, published_at, modified_at. Depois adicionarei mais campos.

CREATE TABLE `comment` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `content` tinytext NOT NULL,
  `author_url` tinytext NOT NULL,
  `author_name` tinytext NOT NULL,
  `author_email` tinytext NOT NULL,
  `created_at` int(11) unsigned NOT NULL DEFAULT '0',
  `post_id` int(11) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `post_id` (`post_id`),
  CONSTRAINT `comment_post_id` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `post` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `content` text NOT NULL,
  `title` tinytext NOT NULL,
  `created_at` int(3) unsigned NOT NULL DEFAULT '0',
  `published_at` int(11) unsigned NOT NULL DEFAULT '0',
  `modified_at` int(11) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Utilizei nenhum framework ou código antigo meu (não que eu não vá fazer isso com este blog um dia ainda). Nossa! Inserir entradas usando mysql_query é um inferno!

Mudei um pouco o style, agora está assim:

pre.blockcode{ border-left: solid 10px #ccf; padding-left: 10px; }
body{ margin-bottom: 20px; text-align: center;  font-size: 90% }
body, td, th, textarea, input{ font-family: Arial; }
#body{ text-align: left; width: 700px; margin: 0 auto; }
.rodape, .rodape a{ text-align: right; color: #f80 }

.comments{ float: left }
a{ color: #333; text-decoration: none }
a:hover{ text-decoration: underline }

form th{font-size: 70%; text-align: right; padding-right: 3px; }
textarea{ width: 500px; height: 100px; }
form{ padding-top: 20px; border-top: solid #888 10px; margin-top: 20px }
.comment .content{ padding-left: 100px; margin-top: 30px }
.comment .info, .comment .info a{ color: #f80 }
.comment .info{ text-align: center; font-size: 70%; }

Para que a data seja retornada corretamente fiz o seguinte:

date_default_timezone_set('America/Sao_Paulo');
setlocale(LC_ALL, "pt_BR", "ptb");
function format_date( $time ){
  return  strftime ("%A, %d %B de %Y às %H:%M", $time );
}
comentários (0) publicado quinta, 12 março de 2009 às 07:49

Comentários

Hoje vou colocar suporte a comentários para este site. Já tenho um banco de dados agora preciso criar uma tabela.

Vou exercitar meu inglês fazendo a estrutura do banco de dados em inglês. Os comentários ficarão na tabela "comment" (usarei singular, pois o manual oficial do mysql geralmente nomeia as tabelas com substantivos no singular). Esta tabela terá os campos:

As dúvidas são várias. Coloco site ou url? Escolhi url, mas confesso que não estou muito satisfeito com essa decisão. Outra pergunta, coloco o "http://" antes do dado ser inserido no banco de dados ou quando eu resgatar o dado? Uso author_url ou somente url? E e-mail, somente email ou author_email? inserted_at, date_time? São muitas as perguntas e eu não tenho boas respostas. Usarei a data nacional, GTM (hora de Greenwich) ou UTC (Tempo Universal Coordenado)? Poderia colocar utc_inserted_at, talvez inserted_at_utc!

Acabei de dar uma olhada no wordpress para me inspirar. Ele prefixa todos os nomes de todos os campos da tabela com "comment_", eu não faria desta forma. Ele também utilizou author_email e author_url. No lugar de author_name ele colocou só author. E tem dois campos de data o date e o date_gmt. É util saber a data do local onde foi postado o comentário, mas saber com certeza esta data.

O Rails trabalha com created_at e updated_at. Talvez seja melhor usar last_modification que é a expressão mais comum para este tipo de coisa (não para caso dos comentários, pois eles não serão editáveis). Talvez modified_at. O wordpress usa para a data de modificação do post post_modified. O formato atom para feeds usa updated e published.

Quero usar UTC para minhas datas!

Agora deu vontade de fazer uma tabelinha com essas informações. Vou puxar mais alguns códigos em php e vou fazer a tabela.

Ruby on Railscreated_atupdated_at
joomlacreatedmodified
drupalcreated (timestamp)changed(int)
CMS Made Simplecreate_datemodified_date
wordpressprefix_date e prefix_date_gmtprefix_modified e prefix_modified_gmt
MediaWikipref_timestamppref_touchedbinary(14), ex: 20080311054101
Textcubecreated writtenmodified
atom*publishedupdated
rss*pubDatelastBuildDateRFC 822
http*Last-Modified
phpBBprefix_time (save_time)prefix_edit_time(int)
xoopspref_created, date, time... pref_modified, pref_lastmodified, pref_updated, last_update, last_modified...(int)
MODxcreatedon publishedoneditatedon

Para a data de inserção de entradas: os CMSs usam created, afinal estamos falando da criação de páginas; o wordpress usa date, provavelmente porque ele usa o mesmo campo para data de publicação e para data que o rascunho foi salvo (confirmar isso); os feeds usam published, claro, para um feed o importante é quando a informação foi publicada; phpBB usa time, uma escolha que sofreu interferência do fato do tipo do campo ser inteiro. Para data de modificação o que mais se repete é modified, updated também parece ser uma boa opção.

Usar ou não _at (created_at)? Salvar como inteiro ou como date_time? Colocar o time_zone como sufixo, prefixo? Usar inteiro é bom e acho que vou começar a fazer isso, com inteiro eu não preciso me preocupar com o time_zone. Em mysql uso a função UNIX_TIMESTAMP(), em php time() e em javascript posso fazer parseInt((new Date).getTime()/1000) (javascrip trabalha com milissegundos).

Ok, vou mudar o identificador do campo inserted_at para created_at do tipo int. Mas não vou implementar os comentários hoje, vou deixar isso para amanhã. E vou aproveitar o embalo e colocar os posts no banco de dados também.

comentários (2) publicado quarta, 11 março de 2009 às 07:37

Olá!

Esta é minha primeira página do meu novo site pessoal. Quero ir melhorando seu código e o deixando mais complexo enquanto adiciono conteúdo a ele. Esta primeira página foi bastante simples. Basicamente fiz uma estrutura html com poucas tags sem me importar com doctype.

<html>
  <head>
    <title>Olá</title>
  </head>
  <body><div id=body>
    <h1>Olá</h1>
	<p>...</p>
	<div class=rodape>...</div>
  </div></body>
</html>

Depois coloquei um "white-space: pre;" no meu "<code>...</code>". Como estou editando essa página direto do fonte sem muitos recursos, somente o meu querido Notepad++, tive que digitar os &lt;, os &gt;, &quot; e, claro, o &amp;. Mudei de ideia, vou tirar, ou melhor, eu tirei o style da tag code. Troquei de code para pre também (tive alguns problemas no ie com a quebra automática). Coloquei esta tag na classe blockcode e criei um estilo usando <style> no cabeçalho. Gosto de nas minhas folhas de estilo escrever muita coisa por linha.

Estou achando estranho a minha forma de falar, tenho que conhecer melhor os jargãos, seus seguinificados, etc. Não sei se o mais certo de dizer é "várias tags style" ou "vários elementos style" (da tag style).

<style>
  code, .blockcode{ color: #333; font-style: italic; font-size: 120%;  }
  body{ text-align: center; font-family: Arial; font-size: 80% }
  #body{ text-align: left; width: 500px; margin: 0 auto; }
</style>

Uma das primeiras coisas que fiz para esta página foi usar a função header do php para mandar o charset correto para que eu não precise codificar as letras com acento. Tirei o charset testei em alguns browser e tudo ficou normal. Vou deixar sem charset por enquanto.

Meu plano é o seguinte, este site será um blog ou um pouco mais que isso. Isto que escrevi hoje será o primeiro post, no próximo post eu colocarei o conteúdo dos posts no banco de dados.

comentários (0) publicado terça, 10 março de 2009 às 22:59
Site do Leonardo Priori