独孤那点事儿 - 2020年11月
type: channel
link: http://sanplit.cn/2020/11/
description: 希望你能够坚强又不失勇敢，期盼你不断辉煌又不缺榜样。
items: PHP抓取一个网站内容
items: MySQL利用存储过程插入数据

PHP抓取一个网站内容
type: item
date: 2020-11-23T16:34:00+08:00
description: 很多时候，抓取一个网站并从特定的标签中提取信息是非常有价值的。这种基本的机制可以用来在网络上搜索有价值的信息。在其他时候，你可能需要得到一个 标签和 SRC 属性的列表，或者 标签和相应的 HREF 属性。这种可能性是无穷无尽的。1、首先新建一个抓取类： capture.phpclass Capture { public $content; 2、抓取目标网站的内容。乍一看，似乎我们应该发出 cURL 请求，或者干脆使用 file_get_contents() 。这些方法的问题是，我们最终将不得不进行大量的字符串操作，很可能不得不过度使用可怕的正则表达式。为了避免这一切，我们将简单地利用已经存在的 PHP 7 类 DOMDocument 。所以我们创建一个 DOMDocument 实例，并将其设置为UTF-8。我们不关心空格，使用方便的 loadHTMLFile() 方法将网站的内容加载到对象中：public function getContent($url) { if (!$this->content) { if (stripos($url, \'http\') !== 0) { $url = \'http://\' . $url; } $this->content = new DOMDocument(\'1.0\', \'utf-8\'); $this->content->preserveWhiteSpace = FALSE; // @ used to suppress warnings generated from // improperly configured web pages @$this->content->loadHTMLFile($url); } return $this->content; } 请注意，我们在调用 loadHTMLFile() 方法之前加上了 @。这并不是为了掩盖错误的编码(!)，就像在PHP5中经常发生的那样！而是当解析器遇到写得不好的HTML时，@ 会抑制产生的通知。相反，当解析器遇到写得不好的HTML时，@会抑制产生的通知。大概我们可以捕获这些通知并记录下来，可能会给我们的 Capture 类提供一个诊断功能。3、接下来，提取感兴趣的标签。我们使用 getElementsByTagName() 方法来实现这一目的。如果我们希望提取所有标记，我们可以提供 * 作为参数：public function getTags($url, $tag) { $count = 0; $result = array(); $elements = $this->getContent($url) ->getElementsByTagName($tag); foreach ($elements as $node) { $result[$count][\'value\'] = trim(preg_replace(\'/\\s+/\', \' \', $node->nodeValue)); if ($node->hasAttributes()) { foreach ($node->attributes as $name => $attr) { $result[$count][\'attributes\'][$name] = $attr->value; } } $count++; } return $result; } 4、提取某些属性而不是标签也可能是有意义的。因此，我们为此定义了另一个方法。在这种情况下，我们需要解析所有的标签并使用 getAttribute() 。你会注意到，有一个DNS域的参数。我们添加这个参数是为了使扫描保持在同一个域内（例如，如果你正在构建一个网络树）：public function getAttribute($url, $attr, $domain = NULL) { $result = array(); $elements = $this->getContent($url) ->getElementsByTagName(\'*\'); foreach ($elements as $node) { if ($node->hasAttribute($attr)) { $value = $node->getAttribute($attr); if ($domain) { if (stripos($value, $domain) !== FALSE) { $result[] = trim($value); } } else { $result[] = trim($value); } } } return $result; } 5、最后执行。 例如,访问传入 ?url=sanplit.cn&ta…

MySQL利用存储过程插入数据
type: item
date: 2020-11-16T11:59:00+08:00
description: 有时本地需要调试，而又因数据小而得不到效果，一条条insert又太麻烦，故而利用存储过程进行数据插入一劳永逸。首先创建所需的表（根据自己需要自行创建）：DROP TABLE IF EXISTS `m_user`; CREATE TABLE `m_user` ( `id` bigint(20) PRIMARY key not null AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `email` varchar(30) DEFAULT NULL, `password` varchar(32) DEFAULT NULL, `status` tinyint(1) NULL DEFAULT 0 ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 然后创建存储过程方法（方法名为add_user_data， 参数为int条数）： CREATE PROCEDURE add_user_data(IN n int) BEGIN DECLARE i INT DEFAULT 1; WHILE i <= n DO INSERT INTO m_user(username, email, password) values(CONCAT(\'username_\', i), CONCAT(i ,\'@qq.com\'), MD5(i)); SET i = i + 1; END WHILE; END; 执行：CALL add_user_data(200000); 这里插入200000条数据如果需要修改，或者删除都需要删除这个存储过程，不然会提示已存在：drop PROCEDURE add_user_data; 搞乱点，可以随便设点随机字符，如何组织自行选择，这只是个不像样的示例。INSERT INTO test_user(username, email, password) values(CONCAT(\'user.\', UPPER(SUBSTRING(REPLACE(UUID(),\'-\',\'\'),1,10))), CONCAT(SUBSTRING(MD5(RAND()), 1, 10) ,\'@qq.com\'), MD5(i)); OVER!