Posts Tagged ‘demotywatory’

Demotywacja demotywatorów II

Author: Marcin Dryka (drymek) | październik 19th, 2009

« Poprzednia część.
Już po krótkim używaniu skryptu, nie trudno się zorientować, że działa on zbyt wolno. Aby przyspieszyć działanie można użyć zachowywania informacji o już ściągniętych demotywatorach. Zatem tekst o tym jak dodać cache:
Klasa Feed. Różni się nieznacznie od oryginału – należy dodać cztery nowe metody:

  public function addToCache($page_url, $image_url)
  {
    Debug::Log("Adding to cache");
    $this->cache[$page_url] = $image_url;
  }

  public function loadCache()
  {
    Debug::Log('Reading cache');
    if (file_exists("cache.csv"))
    {
      $fh = fopen("cache.csv", "r");
      while (($data = fgetcsv($fh, 1000, ",")) !== FALSE)
      {
        $this->cache[$data[0]] = $data[1];
      }
      fclose($fh);
      return $this->cache;
    }
  }

  public function saveCache()
  {
    Debug::Log("Saving cache");
    $fh = fopen('cache.csv', 'w');
    foreach ($this->cache as $page_url=>$image_url)
    {
      fputcsv($fh, array($page_url, $image_url));
    }
    fclose($fh);
  }

  public function isCached($page_url)
  {
    Debug::Log("Checking cache");
    if (empty($this->cache))
    {
      $this->loadCache();
    }
    if (isset($this->cache[$page_url]))
    {
      Debug::Log("Found in cache");
      return $this->cache[$page_url];
    }
    Debug::Log("Not found in cache");
    return false;
  }

oraz użyć ich w odpowiedni sposób. Cały plik wygląda następująco:

url = $url;
  }

  /*
   *  Read remote rss file
   */
  public function getOrginalContent()
  {
    if (is_null($this->url))
    {
      throw new FeedException("You have to set url first!");
    }

    $this->orginalContent = Remote::get_remote_file_content($this->url);
    return $this->orginalContent;
  }

  /*
   * Create a DOMDocument from rss.xml file
   */
  public function getDomOrginalContent()
  {
    if (false === $this->orginalContent || is_null($this->orginalContent))
    {
      throw new FeedException("Can not download rss file");
    }

    $domDocument = new DOMDocument();
    $domDocument->loadXML($this->orginalContent);
    return $domDocument;
  }

  public function addToCache($page_url, $image_url)
  {
    Debug::Log("Adding to cache");
    $this->cache[$page_url] = $image_url;
  }

  public function loadCache()
  {
    Debug::Log('Reading cache');
    if (file_exists("cache.csv"))
    {
      $fh = fopen("cache.csv", "r");
      while (($data = fgetcsv($fh, 1000, ",")) !== FALSE)
      {
        $this->cache[$data[0]] = $data[1];
      }
      fclose($fh);
      return $this->cache;
    }
  }

  public function saveCache()
  {
    Debug::Log("Saving cache");
    $fh = fopen('cache.csv', 'w');
    foreach ($this->cache as $page_url=>$image_url)
    {
      fputcsv($fh, array($page_url, $image_url));
    }
    fclose($fh);
  }

  public function isCached($page_url)
  {
    Debug::Log("Checking cache");
    if (empty($this->cache))
    {
      $this->loadCache();
    }
    if (isset($this->cache[$page_url]))
    {
      Debug::Log("Found in cache");
      return $this->cache[$page_url];
    }
    Debug::Log("Not found in cache");
    return false;
  }
  /*
   * Get image URL from remote webpage
   */
  public function getImage($item)
  {
    if ('link' == $item->nodeName)
    {
      if ($cache = $this->isCached($item->nodeValue))
      {
        return $cache;
      }
      $htmlContent = Remote::get_remote_file_content($item->nodeValue);
      if (false !== $htmlContent)
      {
        //Search image tag
        $pattern = "/bigurl=\".*\"/";
        preg_match($pattern, $htmlContent, $urls);

        //Finally url to the image
        $url = substr($urls[0], 8, -1);
        $this->addToCache($item->nodeValue, $url);
        return $url;
      }
      return 'http://demotywatory.pl/res/img/demotywatory-logo.gif';
    }
  }

  /*
   * Set new description for current item
   */
  public function setImage($item)
  {
    //Find element link
    foreach ($item->childNodes as $rssDomItemChild)
    {
      if ('link' == $rssDomItemChild->nodeName)
      {
        //Download demot page
        $url = $this->getImage($rssDomItemChild);
        break;
      }
    }

    //Find element description
    foreach ($item->childNodes as $rssDomItemChild)
    {
      if ('description' == $rssDomItemChild->nodeName)
      {
        $rssDomItemChild->nodeValue = '<img src="'.$url.'">';
        break;
      }
    }
    Debug::Log('Found url: ['.$url.']');
  }

  /*
   * Convert rss.xml to rss.xml with images in description
   */
  public function transform()
  {
    //Get DOMDocument
    $this->transformedDom = $this->getDomOrginalContent();
    //Find all items
    $rssItems = $this->transformedDom->getElementsByTagName('item');

    //Foreach feed
    Debug::Log('Starting retriving feeds');

    foreach ($rssItems as $rssItem)
    {
      //Set image in description for node
      $this->setImage($rssItem);
    }
    Debug::Log('Finished retriving feeds!');
  }

  /*
   * Get transformed XML
   */
  public function getResults()
  {
    return $this->transformedDom->saveXml();
  }

  /*
   * Save results to file (xml)
   */
  public function save($filename)
  {
    Debug::Log('Saving file ('.$filename.')');
    $fh = fopen($filename, 'w');
    if (!$fh)
    {
      throw new FeedException('Can not open file ('.$filename.') to write!');
    }
    fwrite($fh, $this->getResults());
    fclose($fh);
  }
}

Należy jeszcze zmienić skrypt wywołujący, czyli index.php:

setUrl('http://demotywatory.pl/rss.xml');
//Get rss file content
$feed->getOrginalContent();
//Convert to new format
$feed->transform();
//Save to file
$feed->save('result.xml');
$feed->saveCache();

I to wszystko. Teraz skrypt pobierze informacje jedynie o nowych rssach. Informacje które już posiada w razie potrzeby zostaną użyte ponownie.
Efekt działania można zobaczyć na http://drymek.hostei.com/.
Gotowy do użycia plik rss znajduje się tutaj: http://feeds.feedburner.com/demotywatorator?format=xml

Zestaw wszystkich plików do ściagnięcia: Demotywatorator2