- 背景:
- 基于某些不着边际想法,只为取得HTML页面上的所有“URL”和“文本”,其它的内容都不在关心之列。
- 问题:
- 对于“文本”搜索,如果搜索了除英文以外的语言还好说些,如果要搜索的内容是英文本,
- 那么就难以区分是“标记”还是“本文”了。对于“URL”的搜索,因为“标记”就是英文,
- 这样就绕回到“对于‘文本’搜索”。另外字母的大小写,被转义的字符,引号,尖括号,都得处理。
- 例如:
- <a href="http://www.****.net" >****</a>
- <script src="http://****img.cn/xxxxxxxx.js" type="text/javascript"></script>
- 想要搜索“****”这个字符串,直接以字符串遍历的法能搜索到3个,其实呢只希望搜索到1个。
- 例如:
- <a href="http://bbs.****.net" >论坛</a>
- <a href="http://bbs.****.net" >论 坛</a>
- <a href="http://bbs.****.net" >论 坛</a>
- 想要搜索“论坛”这个字符串,按语义上讲,希望在搜索时能搜到3个。
- 但直接以字符串遍历的法能搜到1个,原因在于加了“空格”后的字符串,
- 计算机不知道对于人来讲意思并没有变。
- 总结:
- 1:直接搜索特定字符串,不多了就是少了。
- 2:尝试过MS的COM库,功能强大且齐全,但耗费的资源也相当多。
- 3:耳熟能详的搜索引擎也跑过几个回合,因没有耐心翻遍所有网页只好放弃。
- 结论:
- 只能把HTML页面完整的解析完毕才能达找到想到的东西,尽管不是全部,但情况要好很多。
- 方法:
- HTML语句结构是:<a href="http://www.****.net" >aaaa</a> 或 <link href="/favicon.ico" />
- 等等一连串类似的语句组成,并且只有嵌套没有循环(脚本只能算上面提到的“文本”)。
- 分界符(这个词本人自己的称呼)使用的是“ <>""''=空格 ”,把两个分界符之间的内容看作一个链表节点,
- “标记”a与“标记”/a是“父”节点与“子”节点的关系,“标记”a与“标记”href是“兄弟”节点的关系。
- 这样的好处是不用关心“标记”含义,就可以把整个页面解析成一个二维链表。
- 纵向可以遍历“标记”和“文本”,横向可以找到“文本”对应用“URL”。
- 当然实际情况要复杂的多,种种异常情况都要考虑。如:转意字符,脚本中的括号对称验证等等,
- 最糟糕是碰到错误的语法,或者根本就不是HTML页面(这个就不属性本文说明范围了)。
- //////////////////////////////以上内容于 2011-12-17 18:01 添加/////////////////////////////////////////
1:较“HTML解析-第一版(C/C++)” 减少了内存拷贝,速度相对提高很多。
2:代码在VS2008下测试通过。#define _UNICODE #define _WIN32_WINNT 0x0600
3:解析方法:类似于构建一个map表(STL模板库里的map不利于阅读,可以参考MFC类库的CMap),最终组成一个二维的单向链表。
4:CHtmlObject 类负责解析HTML“标记”和“属性”。
- //////////////////////////////////////////////////////////////////////////////////////////CHtmlObject.h//////////////////////////////////////////////////////////////////////////
- #pragma once
- /*****************************************************************************************************************
- created: 2011/12/03
- author: hmm7e (hmm7e_z@126.com)
- *****************************************************************************************************************/
- class CHtmlObject
- {
- public:
- //
- static BOOL IsSpace(TCHAR tcLetter);
- protected:
- struct tagNode
- {
- LPCTSTR s_pszKey;
- LPCTSTR s_pszValue;
- struct tagNode * s_pstRight; //attribute of tag
- struct tagNode * s_pstNext; //next tag
- };
- public:
- CHtmlObject(void);
- virtual ~CHtmlObject(void);
- //
- enum {CHARSET_UTF8,CHARSET_UNICODE,CHARSET_MULTIBYTE}TextCharset;
- protected:
- //
- tagNode * InnerAllocNode();
- void InnerFreeNode(tagNode * lpstNode);
- void InnerLinkNextNode(tagNode * lpstNode);
- void InnerLinkRightNode(tagNode * lpstTagNode,tagNode * lpstNode);
- void InnerCleanupNode();
- void InnerCleanupRightNode(tagNode * lpstNode);
- public:
- //
- void AutoTakeSnapshot(PBYTE lpszString,UINT nStringLen);
- void TakeSnapshot(PBYTE lpszString,UINT nStringLen,UINT nFromCharset );
- void DeleteSnapshot();
- //
- void Parse();
- private:
- //
- void InnerParse();
- LPTSTR InnerSplitComment(tagNode * lpstNode,LPTSTR lpszTagString);
- LPTSTR InnerSplitTag(tagNode * lpstNode,LPTSTR lpszTagString);
- LPTSTR InnerSplitContent(tagNode * lpstNode,LPTSTR lpszTagString);
- LPTSTR InnerSplitText(tagNode * lpstNode,LPTSTR lpszTagString);
- LPTSTR InnerSplitScript(tagNode * lpstNode,LPTSTR lpszTagString);
- LPTSTR InnerSplitStyle(tagNode * lpstNode,LPTSTR lpszTagString);
- protected:
- //
- LPTSTR m_pszSnapshotBuffer;
- UINT m_nSnapshotBufferLen;
- UINT m_nSnapshotStringLen;
- //
- tagNode * m_pstHead;
- tagNode * m_pstTail;
- };
- //////////////////////////////////////////////////////////////////////////////////////////CHtmlObject.h//////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////////////CHtmlObject.cpp//////////////////////////////////////////////////////////////////////////
- #pragma once
- /*****************************************************************************************************************
- created: 2011/12/03
- author: hmm7e (hmm7e_z@126.com)
- *****************************************************************************************************************/
- #include "HtmlObject.h"
- //
- BOOL CHtmlObject::IsSpace(TCHAR tcLetter)
- {
- //以下字符在HTML标记里都算是空格。
- return (tcLetter == _T(' ') || tcLetter == _T('\r') ||tcLetter == _T('\n') ||tcLetter == _T('\t') );
- }
- CHtmlObject::CHtmlObject(void)
- {
- m_pszSnapshotBuffer = NULL;
- m_nSnapshotBufferLen = 0;
- m_nSnapshotStringLen = 0;
- m_pstHead = NULL;
- m_pstTail = NULL;
- }
- CHtmlObject::~CHtmlObject(void)
- {
- DeleteSnapshot();
- }
- //
- CHtmlObject::tagNode * CHtmlObject::InnerAllocNode()
- {
- CHtmlObject::tagNode * pstResult = new CHtmlObject::tagNode;
- if( pstResult )
- {
- ::ZeroMemory((LPVOID)pstResult,sizeof(CHtmlObject::tagNode));
- }
- return pstResult;
- }
- void CHtmlObject::InnerFreeNode(CHtmlObject::tagNode * lpstNode)
- {
- if( lpstNode )
- delete lpstNode;
- }
- void CHtmlObject::InnerLinkNextNode(tagNode * lpstNode)
- {
- //链接到“尾”结点。
- //1:如果没有“头”节点,那么表示链表是“空”的。
- //2:如果已经存“头”节点,那么就链接新节点到“尾”节点,并重新记录“尾”节点指针。
- if( m_pstHead == NULL )
- {
- m_pstHead = lpstNode;
- m_pstTail = lpstNode;
- }
- else
- {
- m_pstTail->s_pstNext = lpstNode;
- m_pstTail = lpstNode;
- }
- #ifdef _DEBUG
- if( lpstNode->s_pszKey )
- {
- ::OutputDebugString(_T("--"));
- ::OutputDebugString(lpstNode->s_pszKey);
- ::OutputDebugString(_T("--\r\n"));
- }
- if( lpstNode->s_pszValue )
- {
- ::OutputDebugString(_T("--"));
- ::OutputDebugString(lpstNode->s_pszValue);
- ::OutputDebugString(_T("--\r\n"));
- }
- #endif //_DEBUG
- }
- void CHtmlObject::InnerLinkRightNode(tagNode * lpstTagNode,tagNode * lpstNode)
- {
- //链接到“属性”的“头”节点。
- //1:把现有的“属性”链表,链接到当前新节点的下。
- //2:把当前节点做为“头”节点保存。
- lpstNode->s_pstRight = lpstTagNode->s_pstRight;
- lpstTagNode->s_pstRight = lpstNode;
- #ifdef _DEBUG
- if( lpstNode->s_pszKey )
- {
- ::OutputDebugString(_T("-->"));
- ::OutputDebugString(lpstNode->s_pszKey);
- ::OutputDebugString(_T("<--\r\n"));
- }
- if( lpstNode->s_pszValue )
- {
- ::OutputDebugString(_T("-->"));
- ::OutputDebugString(lpstNode->s_pszValue);
- ::OutputDebugString(_T("<--\r\n"));
- }
- #endif //_DEBUG
- }
- void CHtmlObject::InnerCleanupNode()
- {
- //循环清除所有节点。如果存在“属性”节点一并清除。
- CHtmlObject::tagNode * pstPrev = NULL;
- while( m_pstHead )
- {
- pstPrev = m_pstHead;
- m_pstHead = m_pstHead->s_pstNext;
- //first
- InnerCleanupRightNode(pstPrev);
- //second
- InnerFreeNode(pstPrev);
- }
- m_pstHead = NULL;
- m_pstTail = NULL;
- }
- void CHtmlObject::InnerCleanupRightNode(CHtmlObject::tagNode * lpstNode)
- {
- //循环清除所有“属性”节点。
- CHtmlObject::tagNode * pstHead = lpstNode->s_pstRight;
- CHtmlObject::tagNode * pstPrev = NULL;
- while( pstHead )
- {
- pstPrev = pstHead;
- pstHead = pstHead->s_pstRight;
- InnerFreeNode(pstPrev);
- }
- pstHead = NULL;
- pstPrev = NULL;
- }
- //
- void CHtmlObject::AutoTakeSnapshot(PBYTE lpszString,UINT nStringLen)
- {
- if( lpszString && nStringLen > 0)
- {
- //根据数据头自动判断是否需要转换数据到当前应程所使用的编码。
- if( nStringLen >= 2 )
- {
- if( lpszString[0] == 0xFF && lpszString[1] == 0xFE ) // skip 0xFF,0xFE
- {
- TakeSnapshot(lpszString+2,nStringLen-2,CHtmlObject::CHARSET_UNICODE);
- }
- else if( lpszString[0] == 0xEF && lpszString[1] == 0xBB && lpszString[2] == 0xBF )// skip 0xEF,0xBB,0xBF
- {
- TakeSnapshot(lpszString+3,nStringLen-3,CHtmlObject::CHARSET_UTF8);
- }
- else
- {
- TakeSnapshot(lpszString,nStringLen,CHtmlObject::CHARSET_MULTIBYTE);
- }
- }
- else
- {
- TakeSnapshot(lpszString,nStringLen,CHtmlObject::CHARSET_MULTIBYTE);
- }
- }
- }
- void CHtmlObject::TakeSnapshot(PBYTE lpszString,UINT nStringLen,UINT nFromCharset )
- {
- //delete old snapshot
- DeleteSnapshot();
- if( lpszString && nStringLen > 0 )
- {
- //transform to TCHAR
- if( CHtmlHelper::CHARSET_UTF8 == nFromCharset )
- {
- #ifdef _UNICODE
- m_nSnapshotBufferLen = nStringLen;
- m_pszSnapshotBuffer = new TCHAR[m_nSnapshotBufferLen];
- ::memset((LPVOID)m_pszSnapshotBuffer,0,m_nSnapshotBufferLen*sizeof(TCHAR));
- m_nSnapshotStringLen = ::MultiByteToWideChar(CP_UTF8,0,(LPCSTR)lpszString,nStringLen,m_pszSnapshotBuffer,m_nSnapshotBufferLen);
- #else
- ::OutputDebugString(_T("no support"));
- #endif //_UNICODE
- }
- else if( CHtmlHelper::CHARSET_UNICODE == nFromCharset )
- {
- #ifdef _UNICODE
- m_nSnapshotBufferLen = nStringLen;
- m_pszSnapshotBuffer = new TCHAR[m_nSnapshotBufferLen];
- ::memset((LPVOID)m_pszSnapshotBuffer,0,m_nSnapshotBufferLen*sizeof(TCHAR));
- ::memcpy((LPVOID)m_pszSnapshotBuffer,lpszString,nStringLen);
- #else
- m_nSnapshotBufferLen = nStringLen/2+1;
- m_pszSnapshotBuffer = new TCHAR[m_nSnapshotBufferLen];
- ::memset((LPVOID)m_pszSnapshotBuffer,0,m_nSnapshotBufferLen*sizeof(TCHAR));
- m_nSnapshotStringLen = ::WideCharToMultiByte(CP_ACP,0,(LPWSTR)lpszString,nStringLen,(LPSTR)m_pszSnapshotBuffer,m_nSnapshotBufferLen,NULL,NULL);
- #endif //_UNICODE
- }
- else
- {
- #ifdef _UNICODE
- m_nSnapshotBufferLen = nStringLen;
- m_pszSnapshotBuffer = new TCHAR[m_nSnapshotBufferLen];
- ::memset(m_pszSnapshotBuffer,0,m_nSnapshotBufferLen*sizeof(TCHAR));
- m_nSnapshotStringLen = ::MultiByteToWideChar(CP_ACP,0,(LPCSTR)lpszString,nStringLen,m_pszSnapshotBuffer,m_nSnapshotBufferLen);
- #else
- m_nSnapshotBufferLen = nStringLen;
- m_pszSnapshotBuffer = new TCHAR[m_nSnapshotBufferLen];
- ::memset((LPVOID)m_pszSnapshotBuffer,0,m_nSnapshotBufferLen*sizeof(TCHAR));
- ::memcpy((LPVOID)m_pszSnapshotBuffer,lpszString,nStringLen);
- #endif //_UNICODE
- }
- }
- }
- void CHtmlObject::DeleteSnapshot()
- {
- //先清除树型表。
- InnerCleanupNode();
- if( m_pszSnapshotBuffer )
- delete []m_pszSnapshotBuffer;
- m_pszSnapshotBuffer = NULL;
- m_nSnapshotBufferLen = 0;
- m_nSnapshotStringLen = 0;
- }
- //
- void CHtmlObject::Parse()
- {
- #ifdef _AFX
- CString strTrace;
- strTrace.Format(_T("CHtmlObject::Parse() --begin-->(%d)\r\n"),::GetTickCount());
- ::OutputDebugString(strTrace);
- #endif //_AFX
- InnerParse();
- #ifdef _AFX
- strTrace.Format(_T("CHtmlObject::Parse() --end-->(%d)\r\n"),::GetTickCount());
- ::OutputDebugString(strTrace);
- #endif //_AFX
- }
- //
- void CHtmlObject::InnerParse()
- {
- LPTSTR pszFind = m_pszSnapshotBuffer;
- //跳过所有“空格”
- while( *pszFind != _T('\0') && CHtmlObject::IsSpace(*pszFind) )
- {
- //下一个字符
- pszFind++;
- }
- //直到碰到'\0'就退出
- do
- {
- // 不是“\0”,并且第一个字符为“<”则置换为“\0”,否则什么也不做。
- //这么写的原因就在于InnerSplitContent()返回后 “<”可能已经被置换成“\0”。
- if( *pszFind != _T('\0') && *pszFind == _T('<') )
- {
- //把“<”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //下一个字符。
- pszFind++;
- }
- // 不是“\0”
- if( *pszFind != _T('\0') )
- {
- //是否为注释
- if( *pszFind == _T('!') )
- {
- //申请一个点节。
- tagNode *pstNode = InnerAllocNode();
- //解析注释,返回的是注释后面的内容。
- pszFind = InnerSplitComment(pstNode,pszFind);
- //链接到“链表”。(下)
- InnerLinkNextNode(pstNode);
- }
- else
- {
- //申请一个点节。
- tagNode *pstNode = InnerAllocNode();
- //解析tag,返回的是tag后面的内容。
- pszFind = InnerSplitTag(pstNode,pszFind);
- //解析content返回的是content后面的内容。
- pszFind = InnerSplitContent(pstNode,pszFind);
- //链接到“链表”。(下)
- InnerLinkNextNode(pstNode);
- }
- }
- }while( *pszFind!= _T('\0') );
- }
- LPTSTR CHtmlObject::InnerSplitComment(CHtmlObject::tagNode * lpstNode,LPTSTR lpszTagString)
- {
- LPTSTR pszFind = lpszTagString;
- //指向注释开头(已经跳过“<”字符)
- lpstNode->s_pszKey = pszFind;
- //如果为 <!-- *** -->
- if( ::_tcsnicmp(pszFind+1,_T("--"),2) == 0 )
- {
- //跳过注释标记“头”,开始查找。
- pszFind += 3;
- //查找到注释结尾,并给结尾加“\0”。
- while( ::_tcsnicmp(pszFind,_T("-->"),3) != 0 )
- {
- //下一个字符
- pszFind++;
- }
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- //把“>”置换为“\0”,做为注释结尾
- *(pszFind+2) = _T('\0');
- //指向新的节点或内容。
- pszFind += 3;
- }
- }
- //否则为 <! *** >
- else
- {
- //查找到注释结尾,并给结尾加“\0”。
- while( *pszFind != _T('\0') && *pszFind != _T('>') )
- {
- //下一个字符
- pszFind++;
- }
- //不能是“\0”
- if( *pszFind != _T('\0') )
- {
- //把“>”置换为“\0”,做为注释结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- }
- }
- //找到一个“<”
- while( *pszFind != _T('\0') && *pszFind != _T('<') )
- {
- //下一个字符
- pszFind++;
- }
- return pszFind;
- }
- LPTSTR CHtmlObject::InnerSplitTag(CHtmlObject::tagNode * lpstNode,LPTSTR lpszTagString)
- {
- LPTSTR pszFind = lpszTagString;
- //指向开头(已经跳过“<”字符)
- lpstNode->s_pszKey = pszFind;
- //查找tag结尾,并给结尾加“\0”。
- while( *pszFind != _T('\0') && *pszFind != _T('>') && !CHtmlObject::IsSpace(*pszFind) )
- {
- //下一个字符
- pszFind++;
- }
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- if( *pszFind == _T('>') )
- {
- //把“>”置换为“\0”,做为注释结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- //此tag没有属性,什么也不做了。
- }
- else
- {
- //把“space,\r,\n,\t ”置换为“\0”,做为注释结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- //如果不是结束标记,表示此tag有“属性”还需要解析“属性”。
- if( *lpstNode->s_pszKey != _T('/') )
- {
- //跳过所有“空格”,找到第一个属性。
- while( *pszFind != _T('\0') && CHtmlObject::IsSpace(*pszFind) )
- {
- //下一个字符
- pszFind++;
- }
- //循环分析“属性”。
- while( *pszFind != _T('\0') && *pszFind != _T('<') && *pszFind != _T('>') )
- {
- //例:
- // key="value" key=value
- //跳过空格
- while( *pszFind != _T('\0') && CHtmlObject::IsSpace(*pszFind) )
- {
- //下一个字符
- pszFind++;
- }
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- //申请一个点节。
- tagNode *pstAttributeNode = InnerAllocNode();
- //指向“属性”Key。
- pstAttributeNode->s_pszKey = pszFind;
- //查找key的末尾.
- while( *pszFind != _T('\0') && *pszFind != _T('=') && *pszFind != _T('>') )
- {
- //下一个字符
- pszFind++;
- }
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- if( *pszFind == _T('>') )
- {
- //把“>”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- //链接到“链表”(右)。
- InnerLinkRightNode(lpstNode,pstAttributeNode);
- //已经碰到“>”,需要跳出。
- break;
- }
- else
- {
- //把“=”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- if( *pszFind == _T('"') )
- {
- //跳过“"”
- pszFind++;
- //指向“属性”key的Value。
- pstAttributeNode->s_pszValue = pszFind;
- //查找Value的末尾.
- while( *pszFind != _T('\0') && *pszFind != _T('\"') && *pszFind != _T('>') )
- {
- //下一个字符
- pszFind++;
- }
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- //把“",> ”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- }
- }
- else if( *pszFind == _T('\'') )
- {
- //跳过“'”
- pszFind++;
- //指向“属性”key的Value。
- pstAttributeNode->s_pszValue = pszFind;
- //查找Value的末尾.
- while( *pszFind != _T('\0') && *pszFind != _T('\'') && *pszFind != _T('>') )
- {
- //下一个字符
- pszFind++;
- }
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- //把“",<space> ”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- }
- }
- else
- {
- //指向“属性”key的Value。
- pstAttributeNode->s_pszValue = pszFind;
- //查找Value的末尾.
- while( *pszFind != _T('\0') && *pszFind != _T(' ') && *pszFind != _T('>') )
- {
- //下一个字符
- pszFind++;
- }
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- //把“ ”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- }
- }
- }
- }
- }
- //链接到“链表”(右)。
- InnerLinkRightNode(lpstNode,pstAttributeNode);
- }
- }
- //跳过这个无用的字符。
- if( *pszFind == _T('>') )
- {
- //指向新的节点或内容。
- pszFind++;
- }
- }
- }
- }
- return pszFind;
- }
- LPTSTR CHtmlObject::InnerSplitContent(CHtmlObject::tagNode * lpstNode,LPTSTR lpszTagString)
- {
- LPTSTR pszFind = lpszTagString;
- if( ::_tcsnicmp(lpstNode->s_pszKey,_T("script"),6) == 0 )
- {
- pszFind = InnerSplitScript(lpstNode,pszFind);
- }
- else if( ::_tcsnicmp(lpstNode->s_pszKey,_T("style"),5) == 0 )
- {
- pszFind = InnerSplitStyle(lpstNode,pszFind);
- }
- else
- {
- pszFind = InnerSplitText(lpstNode,pszFind);
- }
- return pszFind;
- }
- LPTSTR CHtmlObject::InnerSplitText(CHtmlObject::tagNode * lpstNode,LPTSTR lpszTagString)
- {
- LPTSTR pszFind = lpszTagString;
- //跳过所有“空格”
- while( *pszFind != _T('\0') && CHtmlObject::IsSpace(*pszFind) )
- {
- //下一个字符
- pszFind++;
- }
- //如果 _T('<') 表示没有文本。
- if( *pszFind != _T('<') )
- {
- //指向可见文本。
- lpstNode->s_pszValue = pszFind;
- //查找文本结尾。
- while( *pszFind != _T('\0') && *pszFind != _T('<') && !CHtmlObject::IsSpace(*pszFind) )
- {
- //下一个字符
- pszFind++;
- }
- //不是“\0”
- if( *pszFind != _T('\0') )
- {
- if( *pszFind == _T('<') )
- {
- //把“<”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- }
- else
- {
- //把“space,\r,\n,\t,”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- //找到一个“<”
- while( *pszFind != _T('\0') && *pszFind != _T('<') )
- {
- //下一个字符
- pszFind++;
- }
- }
- }
- }
- return pszFind;
- }
- LPTSTR CHtmlObject::InnerSplitScript(tagNode * lpstNode,LPTSTR lpszTagString)
- {
- LPTSTR pszFind = lpszTagString;
- #define SCRIPT_MARK_MAX 1024
- UINT nMarkIndex = 0;
- TCHAR szMark[SCRIPT_MARK_MAX] = {_T('\0')}; //max 1024
- //跳过所有“空格”
- while( *pszFind != _T('\0') && CHtmlObject::IsSpace(*pszFind) )
- {
- //下一个字符
- pszFind++;
- }
- if( *pszFind != _T('\0') && *pszFind != _T('<') )
- {
- //指向可见文本。
- lpstNode->s_pszValue = pszFind;
- while( *pszFind != _T('\0') )
- {
- //如果字符被“',"”包围则为字符串,这期间不计算注释。
- if( szMark[nMarkIndex] != _T('\'') && szMark[nMarkIndex] != _T('\"') )
- {
- //如果是// abc 则跳过。
- if( ::_tcsnicmp(pszFind,_T("//"),2) == 0 )
- {
- //跳过注释“头”。
- pszFind +=2;
- //查找注释“尾”。
- while( *pszFind != _T('\0') && *pszFind != _T('\n') )
- {
- pszFind++;
- }
- //跳过注释“尾”。
- if( *pszFind != _T('\0') )
- pszFind++;
- }
- //如果是/* abc */则跳过。
- else if( ::_tcsnicmp(pszFind,_T("/*"),2) == 0 )
- {
- //跳过注释“头”。
- pszFind +=2;
- //查找注释“尾”。
- while( ::_tcsnicmp(pszFind,_T("*/"),2) != 0 )
- {
- pszFind++;
- }
- //跳过注释“尾”。
- if( *pszFind != _T('\0') )
- pszFind +=2;
- }
- }
- if( *pszFind == _T('\\') &&
- ( *(pszFind+1) == _T('\\') ||
- *(pszFind+1) == _T('(') || *(pszFind+1) == _T(')') ||
- *(pszFind+1) == _T('[') || *(pszFind+1) == _T(']') ||
- *(pszFind+1) == _T('{') || *(pszFind+1) == _T('}') ||
- *(pszFind+1) == _T('\'') ||
- *(pszFind+1) == _T('\"') ) )
- {
- //转意字符
- pszFind+=2;
- }
- else if( *pszFind == _T('{') || *pszFind == _T('(') || *pszFind == _T('[') || (*pszFind == _T('\'') || *pszFind == _T('\"')) )
- {
- if( szMark[nMarkIndex] != _T('\'') && szMark[nMarkIndex] != _T('\"') )
- {
- if( nMarkIndex < SCRIPT_MARK_MAX )
- {
- if( nMarkIndex == 0 && szMark[nMarkIndex] == _T('\0') )
- szMark[nMarkIndex] = *pszFind;
- else
- szMark[++nMarkIndex] = *pszFind;
- }
- }
- else if( szMark[nMarkIndex] == *pszFind )
- {
- if( nMarkIndex >0 )
- szMark[nMarkIndex--] = _T('\0');
- else
- szMark[nMarkIndex] = _T('\0');
- }
- pszFind++;
- }
- else if( *pszFind == _T('}') )
- {
- if( szMark[nMarkIndex] == _T('{') )
- {
- if( nMarkIndex >0 )
- szMark[nMarkIndex--] = _T('\0');
- else
- szMark[nMarkIndex] = _T('\0');
- }
- pszFind++;
- }
- else if( *pszFind == _T(')') )
- {
- if( szMark[nMarkIndex] == _T('(') )
- {
- if( nMarkIndex >0 )
- szMark[nMarkIndex--] = _T('\0');
- else
- szMark[nMarkIndex] = _T('\0');
- }
- pszFind++;
- }
- else if( *pszFind == _T(']') )
- {
- if( szMark[nMarkIndex] == _T('[') )
- {
- if( nMarkIndex >0 )
- szMark[nMarkIndex--] = _T('\0');
- else
- szMark[nMarkIndex] = _T('\0');
- }
- pszFind++;
- }
- else if( *pszFind == _T('<') && szMark[0] == _T('\0') ) //nMarkIndex == 0 &&
- {
- //把“<”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- break;
- }
- else
- {
- pszFind++;
- }
- }
- }
- return pszFind;
- }
- LPTSTR CHtmlObject::InnerSplitStyle(CHtmlObject::tagNode * lpstNode,LPTSTR lpszTagString)
- {
- LPTSTR pszFind = lpszTagString;
- #define STYLE_MARK_MAX 1024
- UINT nMarkIndex = 0;
- TCHAR szMark[STYLE_MARK_MAX] = {_T('\0')}; //max 1024
- //跳过所有“空格”
- while( *pszFind != _T('\0') && CHtmlObject::IsSpace(*pszFind) )
- {
- //下一个字符
- pszFind++;
- }
- if( *pszFind != _T('\0') && *pszFind != _T('<') )
- {
- //指向可见文本。
- lpstNode->s_pszValue = pszFind;
- while( *pszFind != _T('\0') )
- {
- //如果字符被“(,',"”包围则为字符串,这期间不计算注释。
- if( szMark[nMarkIndex] != _T('(') && szMark[nMarkIndex] != _T('\'') && szMark[nMarkIndex] != _T('\"') )
- {
- //如果是/* abc */则跳过。
- if( ::_tcsnicmp(pszFind,_T("/*"),2) == 0 )
- {
- //跳过注释“头”,查找注释“尾”。
- pszFind +=2;
- while( ::_tcsnicmp(pszFind,_T("*/"),2) != 0 )
- {
- pszFind++;
- }
- //跳过注释“尾”。
- if( *pszFind != _T('\0') )
- pszFind +=2;
- }
- }
- if( *pszFind == _T('{') || *pszFind == _T('(') || *pszFind == _T('[') || (*pszFind == _T('\'') || *pszFind == _T('\"')) )
- {
- if( szMark[nMarkIndex] != _T('\'') && szMark[nMarkIndex] != _T('\"') )
- {
- if( nMarkIndex < STYLE_MARK_MAX )
- {
- if( nMarkIndex == 0 && szMark[nMarkIndex] == _T('\0') )
- szMark[nMarkIndex] = *pszFind;
- else
- szMark[++nMarkIndex] = *pszFind;
- }
- }
- else if( szMark[nMarkIndex] == *pszFind )
- {
- if( nMarkIndex >0 )
- szMark[nMarkIndex--] = _T('\0');
- else
- szMark[nMarkIndex] = _T('\0');
- }
- pszFind++;
- }
- else if( *pszFind == _T('}') )
- {
- if( szMark[nMarkIndex] == _T('{') )
- {
- if( nMarkIndex >0 )
- szMark[nMarkIndex--] = _T('\0');
- else
- szMark[nMarkIndex] = _T('\0');
- }
- pszFind++;
- }
- else if( *pszFind == _T(')') )
- {
- if( szMark[nMarkIndex] == _T('(') )
- {
- if( nMarkIndex >0 )
- szMark[nMarkIndex--] = _T('\0');
- else
- szMark[nMarkIndex] = _T('\0');
- }
- pszFind++;
- }
- else if( *pszFind == _T(']') )
- {
- if( szMark[nMarkIndex] == _T('[') )
- {
- if( nMarkIndex >0 )
- szMark[nMarkIndex--] = _T('\0');
- else
- szMark[nMarkIndex] = _T('\0');
- }
- pszFind++;
- }
- else if( *pszFind == _T('<') && szMark[0] == _T('\0') ) //nMarkIndex == 0 &&
- {
- //把“<”置换为“\0”,做为结尾。
- *pszFind = _T('\0');
- //指向新的节点或内容。
- pszFind++;
- break;
- }
- else
- {
- pszFind++;
- }
- }
- }
- return pszFind;
- }
- //////////////////////////////////////////////////////////////////////////////////////////CHtmlObject.cpp//////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////////////CHtmlHelper.h//////////////////////////////////////////////////////////////////////////
- #pragma once
- /*****************************************************************************************************************
- created: 2011/12/03
- author: hmm7e (hmm7e_z@126.com)
- *****************************************************************************************************************/
- #include "HtmlObject.h"
- class CHtmlHelper:public CHtmlObject
- {
- public:
- CHtmlHelper(void);
- virtual ~CHtmlHelper(void);
- public:
- //
- LPCTSTR GetFirstLink();
- LPCTSTR GetNextLink();
- LPCTSTR GetFirstContent();
- LPCTSTR GetNextContent();
- LPCTSTR SearchText(LPCTSTR lpszText);
- protected:
- //
- CHtmlObject::tagNode * m_pstCur;
- };
- //////////////////////////////////////////////////////////////////////////////////////////CHtmlHelper.h//////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////////////CHtmlHelper.cpp//////////////////////////////////////////////////////////////////////////
- #pragma once
- /*****************************************************************************************************************
- created: 2011/12/03
- author: hmm7e (hmm7e_z@126.com)
- *****************************************************************************************************************/
- #include "HtmlHelper.h"
- #pragma warning(disable: 4996)
- CHtmlHelper::CHtmlHelper()
- {
- }
- CHtmlHelper::~CHtmlHelper()
- {
- }
- //
- LPCTSTR CHtmlHelper::GetFirstLink()
- {
- LPCTSTR pszResult = NULL;
- m_pstCur = m_pstHead;
- while( m_pstCur && !pszResult )
- {
- if( 0 != ::_tcsnicmp(m_pstCur->s_pszKey,_T("script"),6) &&
- 0 != ::_tcsnicmp(m_pstCur->s_pszKey,_T("style"),5) )
- {
- CHtmlObject::tagNode * pstAttributeCur = m_pstCur->s_pstRight;
- while( pstAttributeCur )
- {
- if( 0 == ::_tcsnicmp(pstAttributeCur->s_pszKey,_T("href"),4) ||
- 0 == ::_tcsnicmp(pstAttributeCur->s_pszKey,_T("src"),3) )
- {
- //return
- pszResult = pstAttributeCur->s_pszValue;
- break ;
- }
- else
- {
- pstAttributeCur = pstAttributeCur->s_pstRight;
- }
- }
- }
- m_pstCur = m_pstCur->s_pstNext;
- }
- return pszResult;
- }
- LPCTSTR CHtmlHelper::GetNextLink()
- {
- LPCTSTR pszResult = NULL;
- while( m_pstCur && !pszResult )
- {
- if( 0 != ::_tcsnicmp(m_pstCur->s_pszKey,_T("script"),6) &&
- 0 != ::_tcsnicmp(m_pstCur->s_pszKey,_T("style"),5) )
- {
- CHtmlObject::tagNode * pstAttributeCur = m_pstCur->s_pstRight;
- while( pstAttributeCur )
- {
- if( 0 == ::_tcsnicmp(pstAttributeCur->s_pszKey,_T("href"),4) ||
- 0 == ::_tcsnicmp(pstAttributeCur->s_pszKey,_T("src"),3) )
- {
- //return
- pszResult = pstAttributeCur->s_pszValue;
- break ;
- }
- else
- {
- pstAttributeCur = pstAttributeCur->s_pstRight;
- }
- }
- }
- m_pstCur = m_pstCur->s_pstNext;
- }
- return pszResult;
- }
- LPCTSTR CHtmlHelper::GetFirstContent()
- {
- LPCTSTR pszResult = NULL;
- m_pstCur = m_pstHead;
- while( m_pstCur && !pszResult )
- {
- if( 0 != ::_tcsnicmp(m_pstCur->s_pszKey,_T("script"),6) &&
- 0 != ::_tcsnicmp(m_pstCur->s_pszKey,_T("style"),5) )
- {
- if( m_pstCur->s_pszValue )
- pszResult = m_pstCur->s_pszValue;
- }
- m_pstCur = m_pstCur->s_pstNext;
- }
- return pszResult;
- }
- LPCTSTR CHtmlHelper::GetNextContent()
- {
- LPCTSTR pszResult = NULL;
- while( m_pstCur && !pszResult )
- {
- if( 0 != ::_tcsnicmp(m_pstCur->s_pszKey,_T("script"),6) &&
- 0 != ::_tcsnicmp(m_pstCur->s_pszKey,_T("style"),5) )
- {
- if( m_pstCur->s_pszValue )
- pszResult = m_pstCur->s_pszValue;
- }
- m_pstCur = m_pstCur->s_pstNext;
- }
- return pszResult;
- }
- //
- LPCTSTR CHtmlHelper::SearchText(LPCTSTR lpszText)
- {
- LPCTSTR pszResult = NULL;
- CHtmlObject::tagNode *pstCur = m_pstHead;
- while( pstCur && !pszResult)
- {
- if( 0 != ::_tcsnicmp(pstCur->s_pszKey,_T("script"),6) &&
- 0 != ::_tcsnicmp(pstCur->s_pszKey,_T("style"),5) )
- {
- if( pstCur->s_pszValue )
- {
- if( (NULL != ::StrStrI(pstCur->s_pszValue,lpszText)) )
- pszResult = pstCur->s_pszValue;
- }
- }
- pstCur = pstCur->s_pstNext;
- }
- return pszResult;
- }
- #pragma warning(default: 4996)
- //////////////////////////////////////////////////////////////////////////////////////////CHtmlHelper.cpp//////////////////////////////////////////////////////////////////////////