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

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

public static function filter_newslink($aid){ $content = mod_news :: get_newscont($aid); //先过滤图片的外链 $content = preg_replace('/<a (.*)>(<img.*>)<//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 则是从后倒数,到字符串结束)

时间: 2024-11-10 12:03:16

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

百度快照没有抓取title和description标签

中介交易 SEO诊断 淘宝客 云主机 技术大厅 最近发现很多SEO爱好者提出这么一个问题:百度快照没有抓取title和description标签,其实之前SEO博客也发表过文章"剖析搜索引擎抓取描述标签错误原因",主要说明描述要如实反应整个网站页面实质内容,而不是一味做关键词叠加,但是这种解决方案对部分网站还是不能通用的.另外文章末尾说到的NOODP标签,含义就是不使用开放式分类目录搜索系统,也就是开放式分类目录搜索系统对这个网站是不适合的. 这里SEO博客先多谈一些NOODP标签吧.

快来帮帮我,今天就要解决抓取网页问题

问题描述 我用C#做一个WINFORM程序,用来抓取某个网页上的TETXBOX再往里面填数据.但这个网页是用openModalDialog方法弹出的窗口,我只能找到它的父窗口找不到它,上午查了半天还是没得法,请各位大虾指点小子一.二. 解决方案 解决方案二:constintWM_GETTEXT=0x000D;constintWM_SETTEXT=0x000C;constintWM_CLICK=0x00F5;[DllImport("User32.dll",EntryPoint="

MySQL和PHP页面同时正确显示中文 &amp;amp; PHP date函数的用法

记录下项目遇到的问题和解决方法. 1. 显示中文 在PHP页面显示的时候,我们通常需要在开头加入下面的代码来让我们的页面能正确显示中文: <pre name="code" class="html"><meta content = text/html; charset=UTF-8 http-equiv = Content-Type> 是的,让页面显示UTF-8, 这样我们在写诸如此类的php代码时 echo '哈哈哈'; 就能正确的在页面上显示

爬取京东本周热卖商品基本信息存入MySQL

爬取京东本周热卖商品基本信息存入MySQL         网络爬虫介绍 概述 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕虫.   产生背景 随着网络的迅速发展,万维网成为大量信息的载体,如何有效地提取并利用这些信息成为一个巨大的挑战.搜索引擎(Search Engine),例如传统的通用搜索引擎AltaVista,Yahoo!和Googl

C#抓取AJAX页面的内容

原文 C#抓取AJAX页面的内容 现在的网页有相当一部分是采用了AJAX技术,所谓的AJAX技术简单一点讲就是事件驱动吧(当然这种说法可能很不全面),在你提交了URL后,服务器发给你的并不是所有是页面内容,而有一大部分是JS脚本,即用<JAVASCRIPT标签表示的,这其中有些是链接了外部的JS文件,有些是内置的JS脚本,这些脚本是在客户端加载了服务器发回来的源码后才执行的,所以不管是采用C#中的WebClient还是HttpRequest都得不到正确的结果,因为这些脚本是在服务器发送完毕后才执

用ASP实现远程抓取网页到本地数据库

数据|数据库|网页     接到一个任务是把中国名牌网站的某些内容添加到我们的网站上,这些网站上有些页面是文章链接列表,点击链接会出现文章的详细内容显示页,根据这个规律,结合正则表达式,XMLHTTP技术,Jscript服务端脚本,以及ADO技术,写了一个小程序,把这些内容抓取到了本地数据库.抓取下来,然后就数据库对数据库导数据就比较方便了.先建立一个Access数据库,结构如下 Id自动编号标识,主键oldID数字旧数据编码Title标题文本Content备注内容 具体实现代码如下 <%@LA

百度近期抓取缓慢和抓取不正常你该怎么办?

大家好,我是哈尔滨虚实网站设计,最近由于工作原因,很少写点什么,今天没事,出来露个面,近期发现大家都在说百度调整,我的网站其实也受到了很大的影响,关键词抓取不正常,排名波动很大,一天几个样,快照更新也很缓慢,嗨哟就是快照和时间不统一,有的关键词快照是最近的,有的是上次的快照,很让我头疼,还有就是新站收录缓慢,关键词放出也很慢,这些说明百度在调整,无论百度如何的调整,我们还是要做些什么,保证稳定的排名和解决一些存在的问题,是吧,今天我就说下如何解决抓取缓慢和抓取不正常,这两点也是我这几天一直在研究

iOS抓取HTML ,CSS XPath解析数据

以前我们获取数据的方式都是使用 AFN 来 Get JSON 数据,比如 点我查看 JSON 数据.http://news-at.zhihu.com/api/4/news/latest 但例如下面的百度贴吧,和豆瓣读书等网站...并不提供我们获取数据的 API 百度贴吧:   百度贴吧数据.png 豆瓣读书: 豆瓣读书数据.png 这时我们可以解析他们的 HTML 来获取我们想要的数据. 工具准备 这时我们需要2个工具,Firefox 和FireBug. 你可以在 http://www.fire

正则表达式 数据抓取

问题描述 最近在做网页信息抓取,但遇到了几个问题,好不纠结,具体问题如下,请给为帮忙解决一下: 在一个长字符串中(HTML文件内容),如何用正则表达式抓取class含有cls_num的对象属性name的值 在一个长字符串中(HTML文件内容),如何抓取所有可见的标签input.textarea.checkbox.radio.select 解决方案 jsoup 神器..百度一下就可以..不用正则了解决方案二:xpath试试http://developer.51cto.com/art/201111/