Home >Database >Mysql Tutorial >MySQL解决抓取文章的html标签替换及其mysql函数的用法说明_MySQL

MySQL解决抓取文章的html标签替换及其mysql函数的用法说明_MySQL

WBOY
WBOYOriginal
2016-06-01 13:18:541195browse

bitsCN.com 刚刚做完了一个手机客户端的攻略的Html5 Web App页面,新的需求出现了:由于攻略文章是抓取过来的,有很多外链,一开始没有过滤。于是先用PHP写了一个过滤函数,然后批量执行更新相关数据库记录即可。

	public static function filter_newslink($aid){		$content = mod_news :: get_newscont($aid);		//先过滤图片的外链		$content = preg_replace('/<a (.*)>(<img .* alt="MySQL解决抓取文章的html标签替换及其mysql函数的用法说明_MySQL" >)<//a>/i', '${2}', $content);			//再过滤文字的外链<a title="" href="">文字</a>为文字		$content = preg_replace('/<a (.*)>(.*)<//a>/i', '${2}', $content);			$data = array('news_id' => $aid, "content" => $content);		$status = mod_news :: update_newscontent($data);		return $status;	}


替换文章的关键词标签可以使用mysql导出后加工再导入数据库,也可以使用存储过程实现。这个的存储过程就不写了。

后来发现有些图片没有抓过来,而产品已经上线,重新抓取数据已是不现实的事情了。于是和同事协商后干脆把图片所在块一起去掉。攻略文章不再展示“卡牌数值”的图片表格。实现方法是采用MySQL的一些不太常用的函数。

SELECT replace(content,SUBSTRING(content FROM POSITION("卡牌数值" IN content) FOR POSITION("-->" IN content)),"</span></h3></p>") as x from CONTENT_TABLE cwhere c.news_id in (select news_id from NEWS_TABLE where col_id = 66)update  CONTENT_TABLE cset c.content = replace(c.content,SUBSTRING(c.content FROM POSITION("卡牌数值" IN c.content) FOR POSITION("-->" IN c.content)),"</span></h3></p>")where c.news_id in (select news_id from NEWS_TABLE where col_id = 66)



鉴于抓来的html结构比较乱比较复杂,也只能这样了。尽管效率一般,不过相关的文章不过几百篇,还可以接受的解决方法。关于其中涉及的SQL函数这里再重温学习一下:

一、MySQL中LOCATE和别名函数POSITION等

函数LOCATE(substr,str) 作用同POSITION(substr IN str)和INSTR(str,substr)

作用:返回子串 substr 在字符串 str 中第一次出现的位置。如果子串 substr 在 str 中不存在,返回值为 0;LOCATE还有一种形式,包含三个参数:LOCATE(substr,str,pos) ,其返回子串 substr 在字符串 str 中的第 pos 位置后第一次出现的位置。INSTR(str,substr)和LOCATE()的双参数形式相同,只是参数顺序不一样而已。

mysql> SELECT LOCATE('bar', 'foobarbar');
-> 4
mysql> SELECT INSTR('foobarbar', 'bar');
-> 4
mysql> SELECT LOCATE('xbar', 'foobar');
-> 0
mysql> SELECT INSTR('xbar', 'foobar');
-> 0
mysql> SELECT LOCATE('bar', 'foobarbar', 7);
-> 7

这个函数是多字节安全的。在 MySQL 3.23 中,这个函数是字母大小写敏感的,当在 MySQL 4.0 中时,如有任一参数是一个二进制字符串,它才是字母大小写敏感的。

以下语句可以实现同样的查询功能:

SELECT `column` FROM `table` where `condition` like `%keyword%’

SELECT `column` from `table` where locate(‘keyword’, `condition`)>0

SELECT `column` from `table` where position(‘keyword’ IN `condition`)

SELECT `column` from `table` where instr(`condition`, ‘keyword’ )>0

速度上后三个比使用 like 稍快了一点点。

二、MySQL的REPLACE用法

用法一:函数REPLACE(str,from_str,to_str)
在字符串 str 中所有出现的字符串 from_str 均被 to_str替换,然后返回这个字符串:
mysql> select REPLACE('www.8783.com/a/detail_list/', 'a', 'list');
-> www.8783.com/list/detlistil_list/

例:把表table中的name字段中的 '斗三国'替换为“全民斗三国”
mysql> update table set name=replace(name,'斗三国','全民斗三国')

这个函数也是多字节安全的。

用法二:REPLACE INTO

在向表中插入数据的时候,经常遇到这样的情况:1. 首先判断数据是否存在; 2. 如果不存在,则插入;3.如果存在,则更新。包括我在内的程序猿们常见的做法有三种:

第一种:MySQL很常见的一种做法,许多新手、甚至许多资深的高级coder也有这么写的,会在代码中封装三个函数,一个函数查询记录是否存在,一个函数实现直接插入,另一个函数对已有记录进行更新。在不同的情况进行调用。这种方法多次excute执行数据操作,势必造成比较大的开销。

第二种:用一条SQL代替三种情况的封装,来实现按需操作,或插入新记录,或更新旧数据。SQL Server中的语句如下:
IF NOT EXISTS(select 1 from NEWS_bak where news_id = 1008)
insert into NEWS_bak(title, keyword, description) values('孙权', '三国','孙权-吴国老大')
else
update NEWS_bak set title = "孙权"and keyword='三国' and description='孙权-吴国老大' where news_id = 1008

说明:对于IF NOT EXISTS的相同表达,MySQL一般用作条件WHERE NOT EXISTS();由于exists(SELECT NULL )也会返回true,故select exists(SELECT NULL )的结果为1。

但是在MySQL 中如何实现此逻辑呢?方法有,且语法更简洁――replace into 。

MySQL replace into 有三种形式:

1. replace into tbl_name(col_name, ...) values(...)
2. replace into tbl_name(col_name, ...) select ...
3. replace into tbl_name set col_name=value, ...

前两种形式使用频度比较高。其中 “into” 关键字可以省略,不过最好加上 “into”,这样意思更加直观。所有列的值均取自在REPLACE语句中被指定的值。所有缺失的列被设置为各自的默认值,这和INSERT一样。您不能从当前行中引用值,也不能在新行中使用值。如果您使用一个例如“SET col_name = col_name + 1”的赋值,则对位于右侧的列名称的引用会被作为DEFAULT(col_name)处理。因此,该赋值相当于SET col_name = DEFAULT(col_name) + 1。

举例:

replace into tableName (id,index) values('1','index-A'),('2','index-B')
此语句用于向表tableName中插入两条记录。 replace into 跟 insert 功能类似,不同点在于:replace into 首先尝试插入数据到表中,如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据; 否则,直接插入新的数据。


为了能够使用REPLACE,您必须同时拥有表的INSERT和DELETE权限。

REPLACE语句会返回一个数,来指示受影响的行的数目。该数是被删除和被插入的行数的和。如果对于一个单行REPLACE该数为1,则一行被插入,同时没有行被删除。如果该数大于1,则在新行被插入前,有一个或多个旧行被删除。如果表包含多个唯一索引,并且新行复制了在不同的唯一索引中的不同旧行的值,则有可能是一个单一行替换了多个旧行。

PHP可以使用mysql_affected_rows()函数获得受影响的行数。受影响的行数可以容易地确定是否REPLACE只添加了一行,或者是否REPLACE也替换了其它行:只需检查该数是否为1(添加)或更大(替换)。

必须注意:插入数据的表必须有主键PRIMARY KEY或者是唯一索引UNIQUE!否则,使用一个REPLACE语句没有意义。该语句会与INSERT相同,因为没有索引被用于确定是否新行复制了其它的行。这时,replace into 会直接插入数据,这将导致表中出现重复的数据。


三、MySQL SUBSTRING 函数的使用

SUBSTRING ( expression , start , length )
参数:
expression 是字符串、二进制字符串、text、image、列或包含列的表达式。不要使用包含聚合函数的表达式。
start是一个整数,指定子串的开始位置。若为负数,则从字符串末尾倒数。
length是一个整数,可选,指定子串的长度(要返回的字符数或字节数)。

函数共有4种格式:

SUBSTRING(str,pos) ,
SUBSTRING(str FROM pos) ,
SUBSTRING(str,pos,len) ,
SUBSTRING(str FROM pos FOR len)


不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。

说明

由于在 text 数据上使用 SUBSTRING 时 start 和 length 指定字节数,因此 DBCS 数据(如日本汉字)可能导致在结果的开始或结束位置拆分字符。此行为与 READTEXT 处理 DBCS 的方式一致。然而,由于偶而会出现奇怪的结果,建议对 DBCS 字符使用 ntext 而非 text 。

返回类型

如果 expression 是支持的字符数据类型,则返回字符数据。如果expression 是支持的 binary 数据类型,则返回二进制数据。一般实际使用中text 数据多以 varchar 的形式返回,image 数据则以 varbinary 的形式返回。

返回字符串的类型与给定表达式的类型相同(表中显示的除外)。

注释

在字符数中必须指定使用 ntext 、char 或 varchar 数据类型的偏移量(start 和 length )。在字节数中必须指定使用 text 、image 、binary 或 varbinary 数据类型的偏移量。

说明 兼容级别可能影响返回值。有关兼容级别的更多信息,请参见 sp_dbcmptlevel 。


其他字符串截取函数有:
1、left(str, length) 从左开始截取字符串
例如:SELECT LEFT(title,1) AS abstract FROM `NEWS_bak`

2、right(str, length) 从右开始截取字符串

3、substring_index(str,delim,count) 按关键字截取字符串
说明:substring_index(被截取字段,关键字,关键字出现的次数)
例:select substring_index("www.8783.com",".",2) as domain from news_table的查询结果是:www.8783
(注:如果关键字出现的次数是负数 如-2 则是从后倒数,到字符串结束)




bitsCN.com

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn