private function getMetadata()
    {
        $this->logger->debug('[Metadata] Retrieving metadata...');

        $values = [];
        // property is a space-separated list of values
        $propertyPattern = '/\s*(dc|dcterm|og|twitter)\s*:\s*(author|creator|description|title|image)\s*/i';

        // name is a single value
        $namePattern = '/^\s*(?:(dc|dcterm|og|twitter|weibo:(article|webpage))\s*[\.:]\s*)?(author|creator|description|title|image)\s*$/i';

        // Find description tags.
        foreach ($this->dom->getElementsByTagName('meta') as $meta) {
            /* @var DOMNode $meta */
            $elementName = $meta->getAttribute('name');
            $elementProperty = $meta->getAttribute('property');
            $content = $meta->getAttribute('content');
            $matches = null;
            $name = null;

            if ($elementProperty) {
                if (preg_match($propertyPattern, $elementProperty, $matches)) {
                    for ($i = count($matches) - 1; $i >= 0; $i--) {
                        // Convert to lowercase, and remove any whitespace
                        // so we can match below.
                        $name = preg_replace('/\s/', '', mb_strtolower($matches[$i]));
                        // multiple authors
                        $values[$name] = trim($content);
                    }
                }
            }

            if (!$matches && $elementName && preg_match($namePattern, $elementName)) {
                $name = $elementName;
                if ($content) {
                    // Convert to lowercase, remove any whitespace, and convert dots
                    // to colons so we can match below.
                    $name = preg_replace(['/\s/', '/\./'], ['', ':'], mb_strtolower($name));
                    $values[$name] = trim($content);
                }
            }
        }

        // get title
        /*
         * This is a very convoluted way of extracting the first matching key of the $values array
         * against a set of options.
         *
         * This could be easily replaced with an ugly set of isset($values['key']) or a bunch of ??s.
         * Will probably replace it with ??s after dropping support of PHP5.6
         */

        $key = current(array_intersect([
            'dc:title',
            'dcterm:title',
            'og:title',
            'weibo:article:title',
            'weibo:webpage:title',
            'title',
            'twitter:title'
        ], array_keys($values)));

        $this->setTitle(isset($values[$key]) ? trim($values[$key]) : null);

        if (!$this->getTitle()) {
            $this->setTitle($this->getArticleTitle());
        }

        // get author
        $key = current(array_intersect([
            'dc:creator',
            'dcterm:creator',
            'author'
        ], array_keys($values)));

        $this->setAuthor(isset($values[$key]) ? $values[$key] : null);

        // get description
        $key = current(array_intersect([
            'dc:description',
            'dcterm:description',
            'og:description',
            'weibo:article:description',
            'weibo:webpage:description',
            'description',
            'twitter:description'
        ], array_keys($values)));

        $this->setExcerpt(isset($values[$key]) ? $values[$key] : null);

        // get main image
        $key = current(array_intersect([
            'og:image',
            'twitter:image'
        ], array_keys($values)));

        $this->setImage(isset($values[$key]) ? $values[$key] : null);
    }