/trunk/scripts/modules/cel/lib-split-auteur.php |
---|
New file |
0,0 → 1,165 |
<?php |
/* |
fork temporaire de cel/jrest/lib/RechercheInfosTaxonBeta.php |
[php-5.4 & co] |
*/ |
require_once('/home/raphael/cel/jrest/lib/Cel.php'); |
// require_once('/home/raphael/cel/jrest/lib/RechercheInfosTaxonBeta.php'); |
require_once('/home/raphael/cel/jrest/lib/NameParser.php'); |
class RechercheInfosTaxonBeta { |
static function getSpaceNoAfter($nom_saisi, $pattern, $offset) { |
if( ($q = strpos($nom_saisi, $pattern, max(0, $offset))) ) { |
// position du premier espace après $pattern, |
// ou position de fin de $pattern autrement |
if(! ($r = strpos($nom_saisi, ' ', $offset + strlen($pattern))) ) |
return $offset + strlen($pattern); |
return $r; |
} |
return FALSE; |
} |
static function supprimerAuteurBis($nom_saisi, &$auteur = null) { |
$strip_pos = 600; |
$before = 600; |
$after = 0; |
// temp var |
$p = $q = NULL; |
if(strpos($nom_saisi, ' ') === FALSE) return FALSE; // pas d'espace, pas de nom d'auteur |
// si "(", break après "Gp)" si présent, sinon, avant "(" |
if( ($p = strpos($nom_saisi, ' Gp)')) ) { |
$after = $p + 4; |
goto sendAuthor; |
} |
// si ".": |
if( ($p = strpos($nom_saisi, '.')) ) { |
// " f. " |
/* SELECT nom_sci, LOCATE(' ', SUBSTRING_INDEX(nom_sci, ' f. ', -1)) AS space_pos |
FROM tb_eflore.bdtfx_v1_02 WHERE nom_sci LIKE '% f. %' HAVING space_pos > 0; */ |
// f. suivi de 1 mot sauf, "Rosa pomifera f. x longicruris" (2) |
/*if( ($q = strpos($nom_saisi, ' f. ', $p - 2)) ) { |
$after = max($after, strpos($nom_saisi, ' ', $q + 4)); // premier espace après ' f. ' |
}*/ |
$after = max($after, self::getSpaceNoAfter($nom_saisi, ' f. ', $p - 2)); |
// " var. " |
// var. n'est pas un repère vraiment adéquat, on sait juste qu'il fait partie du nom sci |
// $after = min($strip_pos, strpos($nom_saisi, ' var. ')); |
$after = max($after, self::getSpaceNoAfter($nom_saisi, ' var. ', $p - 4)); |
// " subsp. " |
// après subsp.: le plus souvent un ' x ', donc pas vraiment de règle (1 ou 2 mots) |
$after = max($after, self::getSpaceNoAfter($nom_saisi, ' subsp. ', $p - 6)); |
// AUTEUR "." |
// autrement, avant un "." dans la partie auteur, il peut y avoir entre 1 et 7 mots à gauche |
// grep -o '^[^.]*\.' liste-auteur.txt|while read f; do grep -o ' '<<<"$f"|wc -l; done|sort -n|tail -1 |
if(!$after) { // si le "." rencontré n'est pas l'un du "nom_sci", c'est de "auteur" |
$before = min($before, $p); |
} |
} |
if( ($p = strpos($nom_saisi, ' x ')) ) { |
$after = max($after, strpos($nom_saisi, ' x ', $p + 3)); |
} |
// " (L.)" et " L." |
if( ($p = strpos($nom_saisi, ' (L.)')) ) { |
$before = min($before, $p); |
} |
// note: on supprime le " L." en amont |
// if( ($p = strpos($nom_saisi, ' L.')) ) $before = min($before, $p); |
// "(" et ")", uniquement dans nom_sci dans le cadre de " Gp)", autrement: auteur |
// XXX: ce cas englobe " (L.)" |
if( ($p = strpos($nom_saisi, '(')) ) { |
$before = min($before, $p); |
} |
// TODO: gérer le " sp." [taxon supérieur], pour l'instant return FALSE |
if( ($p = strpos($nom_saisi, ' sp.')) ) { |
return FALSE; |
} |
// TODO: idem |
if( ($p = strpos($nom_saisi, ' sp ')) ) { |
return FALSE; |
} |
// si "&": auteur, et entre 1 et 10 mots à gauche |
// grep -o '^[^&]*&' liste-auteur.txt|while read f; do grep -o ' '<<<"$f"|wc -l; done|sort -n|tail -1 |
// si ",": auteur, et entre 1 et 5 mots à gauche |
// grep -o '^[^,]*,' liste-auteur.txt|while read f; do grep -o ' '<<<"$f"|wc -l; done|sort -n|tail -1 |
// TRIM auteurs: |
// sed -e 's/[()]//g' liste-auteur.txt|awk '{print $1}'|sed -e 's/[ .,]*$//g'|awk '{print $1}'|sed -r '/^.{0,3}$/d'|sort -u|wc -l |
sendAuthor: |
$x = self::contientAuteur($nom_saisi, $after, $auteur); |
if($x) { |
$n = substr($nom_saisi, 0, min($before, strpos($nom_saisi, $auteur[1]))); |
$auteur = trim(substr($nom_saisi, strlen($n))); |
return trim($n, " \t\n\r\0\x0B(),.&"); |
} |
return FALSE; |
} |
static function contientAuteur($nom_saisi, $start, &$auteur = NULL) { |
static $auteurs; |
// XXX: PHP-5.3 |
// $auteurs = file_get_contents(dirname(__FILE__) . "/../static/auteurs-bdtfx.min.txt"); |
$auteurs = file_get_contents(__DIR__ . "/auteurs-bdtfx.min.txt") or die('no file: auteurs-bdtfx.min.txt'); |
return preg_match('^\s(' . $auteurs . ')^S', $nom_saisi, $auteur, 0, $start); |
} |
static function supprimerAuteur($nom_saisi, &$auteur = null) { |
// TODO: gérer les hybrides |
if(self::estUnHybride($nom_saisi) || self::estUneFormuleHybridite($nom_saisi)) { |
$nom_decoupe = explode(' ', $nom_saisi); |
$derniere_position_hybride = end(array_keys($nom_decoupe, 'x')); |
$nom_saisi_sans_auteur = implode(' ',array_slice($nom_decoupe, 0, $derniere_position_hybride + 2)); |
/* |
var_dump($nom_saisi, $nom_decoupe, $derniere_position_hybride, $nom_saisi_sans_auteur); |
if($auteur != NULL) { |
$c = strpos($nom_saisi, ' x '); |
$auteur = substr($nom_saisi, $c + 3); |
return substr($nom_saisi, 0, $c); |
} |
var_dump(substr($nom_saisi, 0, strpos($nom_saisi, ' x '))); |
echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n";*/ |
} else { |
/* Attention le parseur de nom n'est pas fiable à 100% |
mais ça marche dans la plupart des cas |
à part les formules d'hybridité saisies avec un auteur */ |
$nameparser = new NameParser(); |
$auteur = $nameparser->parse_auth($nom_saisi); |
$nom_saisi_sans_auteur = str_replace($auteur, '', $nom_saisi); |
} |
return trim($nom_saisi_sans_auteur); |
} |
static function estUneFormuleHybridite($nom_saisi) { |
return strpos($nom_saisi,' x ') !== false; |
} |
static function estUnHybride($nom_saisi) { |
return strpos($nom_saisi,'x ') === 0; |
} |
} |
/trunk/scripts/modules/cel/sphinx-maj.log |
---|
7,17 → 7,17 |
[not found] => Array |
( |
[count] => 5040 |
[count] => 6597 |
) |
[too many] => Array |
( |
[count] => 4397 |
[count] => 1065 |
) |
[fixable] => Array |
( |
[count] => 1064 |
[count] => 1448 |
) |
[sauvages] => Array |
27,8 → 27,13 |
[sphinx errors] => Array |
( |
[count] => 152 |
[count] => 0 |
) |
[ref pb] => Array |
( |
[count] => 1543 |
) |
) |
total traité: 11243 |
/trunk/scripts/modules/cel/sphinx-maj-nom-ret.php |
---|
14,14 → 14,30 |
// time php -d memory_limit=1024M sphinx-maj-nom-ret.php 0 > sphinx-maj.log |
// 23 secondes |
// settings |
define('USE_NVJFL', FALSE); |
define('ESCAPE_ON_SPHINX_SYNERROR', TRUE); |
define('TRY_FORCE_START_LINE', TRUE); |
define('TRY_SPLIT', TRUE); |
define('TRY_EXACT', TRUE); |
define('TRY_REF', TRUE); |
define('TRY_SPLIT_AND_AUTEUR', FALSE); |
define('TRY_REMOVE_L', TRUE); |
define('M_TRY_SPLIT', 0x01); |
define('M_TRY_EXACT', 0x02); |
define('M_TRY_REF', 0x04); |
define('M_TRY_SPLIT_AND_AUTEUR', 0x08); |
error_reporting(E_ALL); |
$db = mysql_connect('localhost', 'root', ''); |
$db = mysql_connect('localhost', 'root', '') or die('no mysql'); |
mysql_select_db('tb_cel', $db); |
mysql_query("SET NAMES utf8", $db); |
mysql_query("SET NAMES utf8", $db) or die('no sphinx'); |
$dbs = mysql_connect('127.0.0.1:9306', NULL, NULL, TRUE); |
$req = <<<EOF |
SELECT id_observation, nom_sel, nom_sel_nn,nom_ret,nom_ret_nn,nt,famille |
SELECT id_observation, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, famille, nom_referentiel |
FROM `cel_obs` |
WHERE nom_sel IS NOT NULL AND nom_sel != '' AND |
id_observation BETWEEN %d AND %d AND |
53,8 → 69,10 |
'too many' => ['count' => 0, 'data' => [] ], |
'fixable' => ['count' => 0, 'data' => [] ], |
'sauvages' => ['count' => 0, 'data' => [] ], |
'sphinx errors' => ['count' => 0, 'data' => [] ], ]; |
'sphinx errors' => ['count' => 0, 'data' => [] ], |
'ref pb' => ['count' => 0, 'data' => [] ], ]; |
$sphinx_req = sprintf("SELECT * FROM i_bdtfx %s WHERE MATCH('%%s') LIMIT 5", USE_NVJFL ? ", i_nvjfl" : ""); |
for($current = 0; $current < intval($max/$chunk_size) + 1; $current++) { |
// printf("current = %d, chunk_size = %d, max = %d (rmax = %d) [real limit: %d]\n", $current, $chunk_size, $max, intval($max/$chunk_size) + 1, $current*$chunk_size); |
62,7 → 80,9 |
$data = mysql_query(sprintf($req, $start, $max, $current*$chunk_size, $chunk_size), $db); |
if(!$data) { var_dump(mysql_error()); die('end'); } |
while($d = mysql_fetch_assoc($data)) { |
$n = $d['nom_sel']; |
$n = trim($d['nom_sel']); |
//d: fprintf(STDERR, "$n\n"); |
if(!$n) { |
$stats['no_nom_sel']['count']++; |
// $stats['no_nom_sel']['data'][] = [$d['id_observation'], $n];*/ |
76,34 → 96,106 |
continue; |
} |
$MASQUE = 0; |
if(TRY_REMOVE_L) { |
$n = str_replace(' L.','', $n); |
} |
$orig_n = $n; |
recherche: |
//$s = mysql_query("SELECT * FROM i_bdtfx WHERE MATCH('" . str_replace($from,$to,$n) . "') LIMIT 5", $dbs); |
$s = mysql_query("SELECT * FROM i_bdtfx, i_nvjfl WHERE MATCH('" . $n . "') LIMIT 5", $dbs); |
if(TRY_FORCE_START_LINE && !_has($MASQUE, M_TRY_EXACT)) { |
$n = '^' . $n; |
} |
$s = mysql_query(sprintf($sphinx_req, $n), $dbs); |
if(!$s && ESCAPE_ON_SPHINX_SYNERROR) { |
$s = mysql_query(sprintf($sphinx_req, str_replace($from,$to,$n)), $dbs); |
} |
if(!$s) { |
$stats['sphinx errors']['count']++; |
// $stats['sphinx errors']['data'][] = [$d['id_observation'], $n]; |
// $stats['sphinx errors']['data'][] = [$d['id_observation'], $orig_n]; |
continue; |
} |
$c = mysql_num_rows($s); |
//d: fprintf(STDERR, "\t search [nb:%d] \"%s\" (msk:%d)\n", $c, $n, $MASQUE); |
if($c == 0) { |
if(TRY_SPLIT && !_has($MASQUE, M_TRY_SPLIT)) { |
require_once('lib-split-auteur.php'); |
$MASQUE |= M_TRY_SPLIT; |
// $n = RechercheInfosTaxonBeta::supprimerAuteur($orig_n); |
// list($ret, $m) = RechercheInfosTaxonBeta::contientAuteur($orig_n); |
$ret = RechercheInfosTaxonBeta::supprimerAuteurBis($orig_n, $m); |
if($ret) { |
// printf("===================== SPLIT: contientAuteur \"%s\" [@%s @%s)\n", $orig_n, $ret, $m); |
$n = sprintf('%s @auteur %s', $ret, $m); |
goto recherche; |
} |
} |
if(TRY_SPLIT_AND_AUTEUR && !_has($MASQUE, M_TRY_SPLIT_AND_AUTEUR) && strpos($orig_n, ' ') !== FALSE) { |
require_once('lib-split-auteur.php'); |
$MASQUE |= M_TRY_SPLIT_AND_AUTEUR; |
$ns = RechercheInfosTaxonBeta::supprimerAuteur($orig_n); |
if($ns) { |
$a = trim(substr($orig_n, strlen($n))); |
$n = sprintf("%s @auteur %s", $ns, $a); |
// echo "===================== SPLIT N/A: $n\n"; |
goto recherche; |
} |
} |
$stats['not found']['count']++; |
// $stats['not found']['data'][] = [$d['id_observation'], $n]; |
// $stats['not found']['data'][] = [$d['id_observation'], $orig_n]; |
continue; |
} |
if($c > 1) { |
if($c == 2) { |
if(mysql_fetch_array($s)['group_id'] != |
mysql_fetch_array($s)['group_id']) { |
// recherche donne seulement 2 résultats dans 2 référentiels |
// potentiellement fixable si l'on peut se référer à $d['nom_referentiel'] |
$stats['ref pb']['count']++; |
// $stats['ref pb']['data'][] = [$d['id_observation'], $orig_n]; |
continue; |
} |
} |
if(TRY_EXACT && !_has($MASQUE, M_TRY_EXACT)) { |
$MASQUE |= M_TRY_EXACT; |
$n = '"^' . trim($orig_n) . '$"'; |
goto recherche; |
} |
if(TRY_REF && isset($d['nom_referentiel']) && !_has($MASQUE, M_TRY_REF)) { |
$MASQUE |= M_TRY_REF; |
$n = $orig_n . ' @group_id ' . $d['nom_referentiel']; |
goto recherche; |
} |
$stats['too many']['count']++; |
// $stats['too many']['data'][] = [$d['id_observation'], $n]; |
// $stats['too many']['data'][] = [$d['id_observation'], $orig_n]; |
continue; |
} |
ok: |
$stats['fixable']['count']++; |
// $stats['fixable']['data'][] = [$d['id_observation'], $n]; |
// $stats['fixable']['data'][] = [$d['id_observation'], $orig_n]; |
} |
} |
function _has($v, $r) { |
return ($v & $r) == $r; |
} |
array_walk($stats, function(&$v) { unset($v['data']); }); |
print_r($stats); |
printf("total traité: %d\n", array_sum(array_map(function($v) { return $v['count']; }, $stats))); |