0

有没有办法在找到的所有找到的 url 的末尾preg_replace()添加一个字符串“ ”utm=some&medium=stuff$html_text?

$html_text = 'Lorem ipsum <a href="http://www.me.com">dolor sit</a> amet, 
              <a href="http://www.me.com/page.php?id=10">consectetur</a> elit.';

所以结果应该是

href="http://www.me.com" ›››››
href="http://www.me.com?utm=some&medium=stuff"

href="http://www.me.com/page.php?id=1" ›››››
href="http://www.me.com/page.php?id=1&utm=some&medium=stuff"

因此,如果 url 包含一个问号(第二个 url),它应该在“ ”前面添加一个与号“ &”而不是问号“ ”?utm=some...

最终它只会改变domain me.com.

4

5 回答 5

4

这有点棘手,但如果您的 URL 都用引号引起来(单引号或双引号),则以下代码应该可以工作。它还将处理片段标识符(如#section-2)。

$url_modifier = 'utm=some&medium=stuff';
$url_modifier_domain = preg_quote('www.me.com');

$html_text = preg_replace_callback(
              '#((?:https?:)?//'.$url_modifier_domain.'(/[^\'"\#]*)?)(?=[\'"\#])#i',
              function($matches){
                global $url_modifier;
                if (!isset($matches[2])) return $matches[1]."/?$url_modifier";
                $q = strpos($matches[2],'?');
                if ($q===false) return $matches[1]."?$url_modifier";
                if ($q==strlen($matches[2])-1) return $matches[1].$url_modifier;
                return $matches[1]."&$url_modifier";
              },
              $html_text);

输入:

<a href="http://www.me.com">Lorem</a>
<a href="http://www.me.com/">ipsum</a>
<a href="http://www.me.com/#section-2">dolor</a>
<a href="http://www.me.com/path-to-somewhere/file.php">sit</a>
<a href="http://www.me.com/?">amet</a>,
<a href="http://www.me.com/?foo=bar">consectetur</a>
<a href="http://www.me.com/?foo=bar#section-3">elit</a>.

输出:

<a href="http://www.me.com/?utm=some&medium=stuff">Lorem</a>
<a href="http://www.me.com/?utm=some&medium=stuff">ipsum</a>
<a href="http://www.me.com/?utm=some&medium=stuff#section-2">dolor</a>
<a href="http://www.me.com/path-to-somewhere/file.php?utm=some&medium=stuff">sit</a>
<a href="http://www.me.com/?utm=some&medium=stuff">amet</a>,
<a href="http://www.me.com/?foo=bar&utm=some&medium=stuff">consectetur</a>
<a href="http://www.me.com/?foo=bar&utm=some&medium=stuff#section-3">elit</a>.
于 2013-10-27T15:03:33.347 回答
1

您可以通过使用preg_replace, 2 个模式和两个 replacememts 来实现这一点:

<?php
$add = "utm=some&medium=stuff";
$patterns = array(
                '/(https?:\/\/(?:www)?me\.com(?=.*?\?)[^"]*)/',  # positive lookahead to check if there is a ? mark in url
                '/(https?:\/\/(?:www)?me\.com(?!.*?\?)[^"]*)/' # negative lookahead to check if ? mark is not in
        );
$replacements = array(
                    "$1&".$add, # replacement if first pattern take place
                    '$1?'.$add  # replacement if second pattern take place
            );
$str = 'Lorem ipsum <a href="http://www.me.com">dolor sit</a> amet, <a href="http://www.me.com/page.php?id=10">consectetur</a> elit.';
$str = preg_replace($patterns, $replacements, $str);
echo $str;

/* Output:
Lorem ipsum <a href="http://www.me.com&utm=some&medium=stuff">dolor sit</a> amet, <a href="http://www.me.com/page.php?id=10&utm=some&medium=stuff">consectetur</a> elit.
*/
?>

我喜欢其他使用 DOM 解决方案的答案,然后我测试了每个片段为以下输入所花费的时间:

<a href="http://www.me.com">Lorem</a>
<a href="http://www.me.com/">ipsum</a>
<a href="http://www.me.com/#section-2">dolor</a>
<a href="http://www.me.com/path-to-somewhere/file.php">sit</a>
<a href="http://www.me.com/?">amet</a>,
<a href="http://www.me.com/?foo=bar">consectetur</a>
<a href="http://www.me.com/?foo=bar#section-3">elit</a>.

microtime

$ts = microtime(true);
// codes
printf("%.10f\n", microtime(true) - $ts);

您可以在下面看到它们(毫秒):

@squeamish ossifrage:  0.0001089573
@Cobra_Fast:           0.0003509521
@Emissary:             0.0094890594
@Me:                   0.0000669956

这对我来说很有趣,RegEx做得很好。

于 2013-10-27T14:57:17.603 回答
1

这是一个简单的任务,使用DOMDocument

$html_text = 'Lorem ipsum <a href="http://www.me.com">dolor sit</a> amet, <a href="http://www.me.com/page.php?id=10">consectetur</a> elit.';

$html = new DOMDocument();
$html->loadHtml($html_text);

foreach ($html->getElementsByTagName('a') as $element)
{
    $href = $element->getAttribute('href');
    if (!empty($href)) // only edit the attribute if it's set
    {
        // check if we need to append with ? or &
        if (strpos($href, '?') === false)
            $href .= '?';
        else
            $href .= '&';

        // append querystring
        $href .= 'utm=some&medium=stuff';

        // set attribute
        $element->setAttribute('href', $href);
    }
}

// output altered code
echo $html->C14N();

小提琴: http: //phpfiddle.org/lite/code/wvq-ujk

于 2013-10-27T16:41:24.627 回答
0

如果你想从你的脚本中抽象出所有讨厌的解析,你总是可以使用一个有很多可用的DOM解析器。对于这个示例,我选择了Simple HTML-DOM,因为它是我真正熟悉的唯一一个(诚然,它不是最有效的库,但您并没有做任何密集的事情)。

include 'simple_html_dom.php';
$html = str_get_html($htmlString);

foreach($html->find('a') as $a){
    $url = strtolower($a->href);
    if( strpos($url, 'http://me.com')     === 0 ||
        strpos($url, 'http://www.me.com') === 0 ||
        strpos($url, 'http://') !== 0 // local url
    ){
        $url = explode('?', $url, 2);
        if(count($url)<2) $qry = array();
        else parse_str($url[1], $qry);
        $qry = array_merge($qry, array(
            'utm'    => 'some',
            'medium' => 'stuff'
        ));
        $parts = array();
        foreach($qry as $key => $val)
            $parts[] = "{$key}={$val}";
        $a->href = sprintf("%s?%s", $url[0], implode('&', $parts));
    }
}

echo $html;

在此示例中,我假设me.com是您的网站,并且本地路径也应该符合条件。我还假设查询字符串可能是简单的键:值对。在当前的形式中,如果 URL 已经具有您的查询参数之一,那么它将被覆盖。如果您想保留现有值,则需要交换array_merge函数中参数的顺序。

输入:

<a href="http://me.com/">test</a> 
<a href="http://WWW.me.com/">test</a> 
<a href="local.me.com.php">test</a> 
<a href="http://notme.com">test</a> 
http://me.com/not-a-link
<a href="http://me.com/?id=10&utm=bla">test</a>

输出:

<a href="http://me.com/?utm=some&medium=stuff">test</a> 
<a href="http://www.me.com/?utm=some&medium=stuff">test</a> 
<a href="local.me.com.php?utm=some&medium=stuff">test</a> 
<a href="http://notme.com">test</a> 
http://me.com/not-a-link 
<a href="http://me.com/?id=10&utm=some&medium=stuff">test</a>
于 2013-10-27T16:29:49.310 回答
0

如果您对 DOMDocument 和 utf8 有问题,请尝试以下操作:

$html_text = '<p>This is a text with speical chars ÄÖÜ <a 
href="http://example.com/This-is-my-Page" 
target="_self">here</a>.</p>';
$html_text .= '<p>continue</p>';

$html = new DOMDocument('1.0', 'utf-8');

// Set charset-header for DOMDocument
$html_prepared = '<html>'
  . '<head>'
  . '<meta http-equiv="content-type" content="text/html; charset=UTF-8">'
  . '</head>'
  . '<body>'
  . '<div>' . $html_text . '</div>'
  . '</body>';


$html->loadHtml($html_prepared);


foreach ($html->getElementsByTagName('a') as $element)
{
    $href = $element->getAttribute('href');
    if (!empty($href)) // only edit the attribute if it's set
    {
        // check if we need to append with ? or &
        if (strpos($href, '?') === false)
            $href .= '?';
        else
            $href .= '&';

        // append querystring
        $href .= 'utm=some&medium=stuff';

        // set attribute
        $element->setAttribute('href', $href);
    }
}


// 1) Remove doctype-declaration
$html->removeChild($html->firstChild);
// 2) Remove head
$html->firstChild->removeChild($html->firstChild->firstChild);
// 3) Only keep body's first Child
$html->replaceChild($html->firstChild->firstChild->firstChild, $html->firstChild);

print $html->saveHTML();
于 2014-05-23T14:49:25.763 回答