Advertisement
Cavitt

TibiaWiki Monster Scraper

Apr 25th, 2014
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 11.96 KB | None | 0 0
  1. <?php
  2.     require("library.php");
  3.    
  4.     function xmlpp($xml, $html_output=false) {  
  5.         $xml_obj = new SimpleXMLElement($xml);  
  6.         $level = 4;  
  7.         $indent = 0; // current indentation level  
  8.         $pretty = array();  
  9.          
  10.         // get an array containing each XML element  
  11.         $xml = explode("\n", preg_replace('/>\s*</', ">\n<", $xml_obj->asXML()));  
  12.      
  13.         // shift off opening XML tag if present  
  14.         if (count($xml) && preg_match('/^<\?\s*xml/', $xml[0])) {  
  15.           $pretty[] = array_shift($xml);  
  16.         }  
  17.      
  18.         foreach ($xml as $el) {  
  19.           if (preg_match('/^<([\w])+[^>\/]*>$/U', $el)) {  
  20.               // opening tag, increase indent  
  21.               $pretty[] = str_repeat(' ', $indent) . $el;  
  22.               $indent += $level;  
  23.           } else {  
  24.             if (preg_match('/^<\/.+>$/', $el)) {              
  25.               $indent -= $level;  // closing tag, decrease indent  
  26.             }  
  27.             if ($indent < 0) {  
  28.               $indent += $level;  
  29.             }  
  30.             $pretty[] = str_repeat(' ', $indent) . $el;  
  31.           }  
  32.         }    
  33.         $xml = implode("\n", $pretty);    
  34.         return ($html_output) ? htmlentities($xml) : $xml;  
  35.     }
  36.    
  37.     function getResult($results) {
  38.         if($results) {
  39.             foreach ($results as $item) {
  40.                 $result = trim($item->nodeValue);
  41.                 return $result;
  42.             }
  43.         }
  44.         return false;
  45.     }
  46.    
  47.     function writeLog($type, $msg) {
  48.         file_put_contents("monsters/logs/".$type.".txt", $msg."\n", FILE_APPEND | LOCK_EX);
  49.     }
  50.  
  51.     function loadMonster($name) {
  52.         $path = "monsters/sample.xml";
  53.         $new = true;
  54.         if(file_exists("monsters/source/".$name.".xml")){
  55.             $path = "monsters/source/".$name.".xml";
  56.             $new = false;
  57.         }
  58.         $xml = simplexml_load_file($path);
  59.         if ($xml) {
  60.             return array($xml, $new);
  61.         }
  62.         return false;
  63.     }
  64.  
  65.     function getMonsterLoot($link) {
  66.         $dom = new DOMDocument();
  67.         @$dom->loadHTMLFile($link);
  68.         $lootitems = array();
  69.         $i = 1;
  70.         while ($i <= 60) {
  71.             $xpath = new DOMXPath($dom);
  72.             $base = "//*[@id='mw-content-text']/table[2]//tr[" . $i . "]//td//text()";
  73.             $items = $xpath->query($base);
  74.             $loot = array();
  75.             foreach ($items as $item)
  76.                 $loot[] = $item->nodeValue;
  77.             if(count($loot) > 0) {
  78.                 //handling count ranges
  79.                 $count_range = explode('-', $loot[0]);
  80.                 $count = ($count_range[1]) ? $count_range[1] : $loot[0];
  81.                 $itemname = strtolower(trim($loot[1]));
  82.                 $chance = (str_replace('%', '', $loot[4]) * 1000);
  83.                 if((strlen($itemname) > 1) && (strcasecmp($itemname, "empty") != 0) && is_numeric($count) && is_numeric($chance))
  84.                     $lootitems[] = array('name'=>$itemname,'count'=>$count,'chance'=>$chance);
  85.             }
  86.             $i++;
  87.         }
  88.         return $lootitems;
  89.     }
  90.    
  91.     function getMonsterDetails($name, $new) {
  92.         $dom = new DOMDocument();
  93.         @$dom->loadHTMLFile("http://tibia.wikia.com/wiki/" . str_ireplace(" ", "_", $name) . ((in_array($name, $duplicateCreatures)) ? '_(Creature)' : ''));
  94.         $xpath = new DOMXPath($dom);
  95.         $w_name = trim(str_ireplace("(creature)", "", getResult($xpath->query("//*[@id='WikiaPageHeader']//h1"))));
  96.         if(strcasecmp($w_name, $name) == 0) { //correct page (hopefully)
  97.             $w_pushable = getResult($xpath->query("//*[@id='mw-content-text']//tr[td/b[contains(text(),'Pushable')]]//td[2]//a//img/@alt"));
  98.             $w_pushObjects = getResult($xpath->query("//*[@id='mw-content-text']//tr[td/b[contains(text(),'Push Objects')]]//td[2]//a//img/@alt"));
  99.             $pushable = (strcasecmp($w_pushable, 'Tick.jpg') == 0) ? 1 : 0;
  100.             $pushObjects = (strcasecmp($w_pushObjects, 'Cross.jpg') == 0) ? 0 : 1;
  101.            
  102.             //general stats
  103.             $w_hp = trim(getResult($xpath->query("//*[@id='mw-content-text']/table//tr[2]/td[2]/text()[1]")));
  104.             $w_exp = trim(getResult($xpath->query("//*[@id='mw-content-text']/table//tr[2]/td[2]/text()[2]")));
  105.             $w_sumConString = trim(getResult($xpath->query("//*[@id='mw-content-text']//tr[td//a[@href='/wiki/Summon']]/td[2]/text()[1]")), " )");
  106.             $summCon = explode('/', $w_sumConString);
  107.            
  108.             $hp = is_numeric($w_hp) ? $w_hp : 0;
  109.             $exp = is_numeric($w_exp) ? $w_exp : 0;
  110.             $summon = is_numeric($summCon[0]) ? $summCon[0] : 0;
  111.             $convince = is_numeric($summCon[1]) ? $summCon[1] : 0;
  112.            
  113.             //immunities
  114.             $immunities = array();
  115.             $w_immunities = $xpath->query("//*[@id='mw-content-text']//tr[td/b[contains(text(),'Immun')]]//td[2]//a//text()");
  116.             foreach ($w_immunities as $immunity)
  117.                 $immunities[] = $immunity->nodeValue;
  118.  
  119.             //elements
  120.             $elements = array();
  121.             $lastElement = NULL;
  122.             $w_strengths = $xpath->query("//*[@id='mw-content-text']//tr[td/b[contains(text(),'Strong')]]//td[2]//span[contains(@class,'dmg')]");
  123.             foreach ($w_strengths as $strength) {
  124.                 if(is_null($lastElement)) {
  125.                     $lastElement = $strength->nodeValue;
  126.                 } else {
  127.                     $elements[$lastElement] = intval(trim($strength->nodeValue, ' -+%'));
  128.                     $lastElement = NULL;
  129.                 }
  130.             }
  131.            
  132.             //log abilities
  133.             writeLog((($new) ? 'added' : 'updated') . '-abilities', '[' . $name . '] - ' . getResult($xpath->query("//*[@id='mw-content-text']//tr[td/b[contains(text(),'Abilities')]]//td[2]")));
  134.            
  135.             $lastElement = NULL; //reset jic
  136.             $w_weaknesses = $xpath->query("//*[@id='mw-content-text']//table[1]//tr//td//div//table//tr[td/b[contains(text(),'Weak')]]//td[2]//span[contains(@class,'dmg')]");
  137.             foreach ($w_weaknesses as $weakness) {
  138.                 if(is_null($lastElement))
  139.                     $lastElement = $weakness->nodeValue;
  140.                 else {
  141.                     $elements[$lastElement] = intval('-' . trim($weakness->nodeValue, ' -+%'));
  142.                     $lastElement = NULL;
  143.                 }
  144.             }
  145.            
  146.             //sounds
  147.             $w_sounds = explode(";", rtrim(getResult($xpath->query("//*[@id='mw-content-text']//span[@class='creaturesounds']")), '.'));
  148.             $sounds = array();
  149.             foreach ($w_sounds as $sound) {
  150.                 $trimmed = trim(str_ireplace(array('"', ';'), "", $sound));
  151.                 if(strlen($trimmed) > 1)
  152.                     $sounds[] = $trimmed;
  153.             }
  154.            
  155.             //loot
  156.             $lootitems = @getMonsterLoot("http://tibia.wikia.com/wiki/Loot_Statistics:" . str_ireplace(" ", "_", $name) . ((in_array($name, $duplicateCreatures)) ? '_(Creature)' : ''));
  157.            
  158.             return array('exp'=>$exp, 'hp'=>$hp, 'convince'=>$convince, 'summon'=>$summon, 'pushable'=>$pushable, 'canpushitems'=>$pushObjects, 'sounds'=>$sounds, 'elements'=>$elements, 'immunities'=>$immunities, 'lootitems'=>$lootitems);
  159.         } else {
  160.             writeLog('404', "[Invalid Page] - http://tibia.wikia.com/wiki/" . $name);
  161.         }
  162.         return false;
  163.     }
  164.    
  165.     /* Main */
  166.     //TODO: getItemXMLDuplicates(); //loads xml and adds any reoccuring item name in an array
  167.    
  168.     $limit = 0; //set to 0 for all
  169.     $n = 0;
  170.     $itemlist = simplexml_load_file("items.xml");
  171.     foreach ($monsterList as $name) {
  172.         $n++;
  173.         if($n >= $limit && $limit > 0) // for testing
  174.             die("end of the line.");
  175.  
  176.         $load = loadMonster(strtolower($name));
  177.         $new = $load[1];
  178.         $monster = $load[0];
  179.         $boss = in_array($name, $bossList);
  180.         $illusionable = in_array($name, $illusionables);
  181.         $details = getMonsterDetails($name, ($new) ? true : false);
  182.         if($monster) {
  183.        
  184.             //basic notification triggers:
  185.             if($details['exp'] <= 0)
  186.                 writeLog('missing-stats', "[Missing Experience] - " . $name);
  187.             if($details['hp'] <= 0)
  188.                 writeLog('missing-stats', "[Missing Health] - " . $name);
  189.                
  190.             //main list stats
  191.             $monster['name'] = $name;
  192.             $monster['nameDescription'] = (($boss) ? '' : (strspn(strtolower($name), 'aeiou') ? 'an ' : 'a ')) . strtolower($name);
  193.             $monster['experience'] = $details['exp'];
  194.             $monster['manacost'] = $details['summon'];
  195.             $monster->health['now'] = $details['hp'];
  196.             $monster->health['max'] = $details['hp'];
  197.            
  198.             //defined attributes (looktype [, TODO: corpse, race])
  199.             if($new) {
  200.                 $outfit = array_search(strtolower($name), $knownLookTypes);
  201.                 if($outfit !== false)
  202.                     $monster->look['type'] = $outfit;
  203.                 else
  204.                     writeLog('missing-looktypes', "[Missing Looktype] - " . $name);
  205.             }
  206.            
  207.             //flags (bosses get the lureable 1 attribute)
  208.             $old_flags = array();
  209.             if(!$new) {
  210.                 //loop through all current flags of monster before clearing
  211.                 foreach ($monster->flags->children() as $old_flag)
  212.                     foreach($old_flag->attributes() as $k => $v)
  213.                         $old_flags[$k] = (string) $v;
  214.                 //it's safe to loop through and delete
  215.                 foreach ($monster->flags->children() as $old_flag)
  216.                     unset($monster->flags->flag);
  217.             }
  218.            
  219.             $monster->flags->flag[0]['attackable'] = (!$new && isset($old_flags['attackable'])) ? $old_flags['attackable'] : 1;
  220.             $monster->flags->flag[1]['hostile'] = (!$new && isset($old_flags['hostile'])) ? $old_flags['hostile'] : 1;
  221.             $monster->flags->flag[2]['summonable'] = ($details['summon'] > 0) ? 1 : 0;
  222.             $monster->flags->flag[3]['convinceable'] = ($details['convince'] > 0) ? 1 : 0;
  223.             $monster->flags->flag[4]['illusionable'] = ($illusionable) ? 1 : 0;
  224.             $monster->flags->flag[5]['pushable'] = ($details) ? $details['pushable']: 0;
  225.             $monster->flags->flag[6]['canpushitems'] = ($details) ? $details['canpushitems'] : 1;
  226.             $monster->flags->flag[7]['canpushcreatures'] = (!$new && isset($old_flags['canpushcreatures'])) ? $old_flags['canpushcreatures'] : 1;
  227.             $monster->flags->flag[8]['targetdistance'] = (!$new && isset($old_flags['targetdistance'])) ? $old_flags['targetdistance'] : 1;
  228.             $monster->flags->flag[9]['staticattack'] = (!$new && isset($old_flags['staticattack'])) ? $old_flags['staticattack'] : 90;
  229.             $monster->flags->flag[10]['runonhealth'] = (!$new && isset($old_flags['runonhealth'])) ? $old_flags['runonhealth'] : 0;
  230.             $monster->flags->flag[11]['lureable'] = ($boss) ? 1 : 0;
  231.            
  232.             //elements
  233.             unset($monster->elements);
  234.             if(count($details['elements']) > 0) {
  235.                 $elements = $monster->addChild('elements', '');
  236.                 foreach ($details['elements'] as $element => $value) {
  237.                     $knownElement = $knownElements[$element];
  238.                     if(!is_null($knownElement)) {
  239.                         $elementPercent = $elements->addChild('element', '');
  240.                         $elementPercent->addAttribute($knownElement, $value);
  241.                     }  
  242.                 }
  243.             }
  244.             //immunities
  245.             unset($monster->immunities);
  246.             if(count($details['immunities']) > 0) {
  247.                 $immunities = $monster->addChild('immunities', '');
  248.                 foreach ($details['immunities'] as $immunity) {
  249.                     $knownImmunity = $knownImmunities[$immunity];
  250.                     if(!is_null($knownImmunity)) {
  251.                         $monsterImmunity = $immunities->addChild('immunity', '');
  252.                         $monsterImmunity->addAttribute($knownImmunity, 1);
  253.                     }  
  254.                 }
  255.             }
  256.            
  257.             //voices (slightly buggy)
  258.             unset($monster->voices);
  259.             if($details){
  260.                 if(count($details['sounds']) > 0) {
  261.                     $voices = $monster->addChild('voices', '');
  262.                     $voices->addAttribute('interval', 5000);
  263.                     $voices->addAttribute('chance', 10);
  264.                     foreach ($details['sounds'] as $str) {
  265.                         $voice = $monster->voices->addChild('voice', '');
  266.                         $voice->addAttribute('sentence', trim($str));
  267.                         if(strtoupper($str) == $str) //if all caps, must be yelling :)
  268.                             $voice->addAttribute('yell', 1);
  269.                     }
  270.                 }
  271.             }
  272.            
  273.             //loot
  274.             unset($monster->loot);
  275.             $lootitems = $details['lootitems'];
  276.             if($lootitems) {
  277.                 $monster->addChild('loot', '');
  278.                 foreach ($lootitems as $loot) {
  279.                     $itemcount = count($itemlist->xpath('/items/item[@name="' . $loot['name'] . '"]'));
  280.                    
  281.                     if($itemcount <= 0)
  282.                         writeLog('missing-items', "[" . $loot['name'] . "] - " . $name);
  283.                     elseif($itemcount > 1)
  284.                         writeLog('duplicate-items', "[" . $loot['name'] . "][".$itemcount."] - " . $name);
  285.                    
  286.                     $item = $monster->loot->addChild('item', '');
  287.                     $knownDupe = $duplicateItems[strtolower($loot['name'])];
  288.                     if(!is_null($knownDupe)) {
  289.                         $item->addAttribute('id', $knownDupe);
  290.                     } else {
  291.                         $item->addAttribute('name', $loot['name']);
  292.                     }
  293.                     if($loot['count'] > 1)
  294.                         $item->addAttribute('count', $loot['count']);
  295.                     $item->addAttribute('chance', $loot['chance']);
  296.                 }
  297.             }
  298.            
  299.             $color = ($new) ? 'green' : 'orange';
  300.             $folder = ($new) ? 'added' : 'updated';
  301.            
  302.             //save monster
  303.             $path = "monsters/" . $folder . "/" . (strtolower($name)) . ".xml";
  304.             $string = xmlpp($monster->asXML());
  305.             file_put_contents($path, $string);
  306.            
  307.             //verbose
  308.             echo("<span style='color:" . $color . "'>[" . $folder . "]</span> monster: <b>" . (strtolower($name)) . ".xml</b><br/>");
  309.         }
  310.     }
  311. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement