完善自己的html parse

2024-03-02 17:58
文章标签 html 完善 frontend parse

本文主要是介绍完善自己的html parse,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       说来惭愧,我发现自己写的那个html parse过于理想化,解析xml还差不多,想解析现今的html,估计是不大可能的,所以我把代码重写了一遍,数据结构改成双向链表,这样解析速度更快,最大程度地对html进行容错处理,试验时发现的确可以解析普通html字符串,不需要再严格符合那个xhtml标准了。而且在链式调用的传递参数上不需要再传入dom类型的参数,这样写起来就更加简便了。

        好了,废话不多说,看代码:

#include<iostream>
#include<string>
#include "windows.h"
#include "wininet.h"
using namespace std;
#pragma comment(lib,"wininet.lib")
wstring UTF8ToUnicode( const string& str )
{
int len = str.length();
int unicodeLen = ::MultiByteToWideChar( CP_UTF8, 0, str.c_str(), -1, NULL, 0 );
wchar_t * pUnicode;
pUnicode = new wchar_t[unicodeLen+1];
memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
MultiByteToWideChar( CP_UTF8, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen );
wstring rt = ( wchar_t* )pUnicode;
delete pUnicode;
return rt;
}
string UnicodeToANSI( const wstring& str )
{
char* pElementText;
int iTextLen;
// wide char to multi char
iTextLen = WideCharToMultiByte( CP_ACP, 0, str.c_str(), -1, NULL, 0, NULL, NULL );
pElementText = new char[iTextLen + 1];
memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
WideCharToMultiByte( CP_ACP, 0, str.c_str(), -1, pElementText, iTextLen, NULL, NULL );
string strText = pElementText;
delete[] pElementText;
return strText;
}
class node;
class dom;
class nodecollect{
private:
node *n;
int length;
public:
nodecollect();
~nodecollect();
int getlength();
void add(node *nn);
node* item(int i);
};
class node{
private:
int start;
int len;
char name[20];
public:
char* nodehtml();
char* innerhtml();
char* outerhtml();
char* innertext();
char* getattr(char* str);
char* tagname();
void setname(char *str);
node* getparent();
nodecollect* getchild(); 
node* getnext();
node* getprevious();
nodecollect* getbytagname(char *tagname);
node *next;
node *previous;
void setstart(int i);
void setlen(int i);
int getstart();
int getlen();
dom *d;
};
class dom{
private:
char *text;
node *start;
node *end;
int count;
int parse(char *s);
public:
~dom();
char *gettext();
void load(char *str);
node* getitem(int i);
int getcount();
node *getbyid(char* id);
void praseurl(char *url);
nodecollect* getbytagname(char *tagname);
};
void dom::load(char* str){
start=0;
end=0;
count=0;
int l=strlen(str);
text=new char[l+1];
strcpy(text,str);
char *t=text;
parse(t);
}
int dom::getcount(){
return count;
}
char *dom::gettext(){
return text;
}
node* dom::getitem(int i){
node* n1=start;
while(i--){
if(n1){
n1=n1->next;
}else{
return 0;
}
}
return n1;
}
node *dom::getbyid(char *id){
for(int i=0;i<this->getcount();i++){
if(::stricmp(this->getitem(i)->getattr("id"),id)==0){
return this->getitem(i);
}
}
return 0;
}
nodecollect* dom::getbytagname(char *tagname){
nodecollect *nnode=new nodecollect;
for(int i=0;i<this->getcount();i++){
// cout<<strlen(this->getitem(i)->tagname(*this))<<endl;
if(::stricmp(this->getitem(i)->tagname(),tagname)==0){
nnode->add(this->getitem(i));
}
}
return nnode;
}
dom::~dom(){
delete[] text;
node *n1=start,*n2;
if(n1){
while(n1->next!=0){
n2=n1;
n1=n1->next;
delete n2;
}
}
}
void dom::praseurl(char *url){
HINTERNET ie=InternetOpen("sx",INTERNET_OPEN_TYPE_PRECONFIG,0,0,0);
HINTERNET ieo=InternetOpenUrl(ie,url,0,0,INTERNET_FLAG_RELOAD,0);
DWORD read=0;
char b[100]={0};
char *bb=0;
string str="";
while(1){
InternetReadFile(ieo,b,99,&read);
if(read==0){
break;
}
str+=b;
memset(b,0,100);
}
string temp=UnicodeToANSI( UTF8ToUnicode(str));
bb=(char*)temp.c_str();
load(bb);
InternetCloseHandle(ieo);
InternetCloseHandle(ie);
}
int dom::parse(char *s){
int i1=0,i2=0,i3=0,i4=0;
while(*s!=0){
if(*s==0){
return (long)s;
}
if(i3==1 || i4==1){
if(*s=='\"' && *(s-1)!='\\'){
if(i1==0){
i1=1;
}else{
i1=0;
}
}
if(*s=='\'' && *(s-1)!='\\'){
if(i2==0){
i2=1;
}else{
i2=0;
}
}
}
if(*s=='<' && *(s+1)=='!'){
if(i1==0 && i2==0 && i4==0){
i3=1;
node *nn=new node;
nn->setstart(s-text);
nn->setlen(0);
nn->d=this;
nn->setname(s+1);
nn->next=0;
nn->previous=0;
if(start){
node *n1=start;
while(n1->next!=0){
n1=n1->next;
}
n1->next=nn;
nn->previous=n1;
end=nn;
}else{
start=nn;
end=nn;
}
int s1=(long)s;
while(*s){
if(*s=='\"'){
if(i1==0){
i1=1;
}else{
i1=0;
}
}
if(*s=='\''){
if(i2==0){
i2=1;
}else{
i2=0;
}
}
if(*s=='>' && ((*(s-1)=='-' && *(s-2)=='-') ||  (*(s-1)=='/"' && *(s-2)=='d' && *(s-3)=='t' && *(s-4)=='d' && *(s-5)=='.') || (*(s-1)=='l' && *(s-2)=='m' && *(s-3)=='t' && *(s-4)=='h' && *(s-5)==' '))){
if(i1==0 && i2==0){
//cout<<(long)s+1-s1<<endl;
nn->setlen((long)s+1-s1);
s++;
break;
}
}
s++;
}
count++;
}
}
if(*s=='<' && *(s+1)!='/' && *(s+1)!='!'){
if(i1==0 && i2==0 && i4==0){
i3=1;
node *nn=new node;
//cout<<s-text<<endl;
nn->setstart(s-text);
nn->setlen(0);
nn->d=this;
nn->setname(s+1);
nn->next=0;
nn->previous=0;
if(start){
node *n1=start;
while(n1->next!=0){
n1=n1->next;
}
n1->next=nn;
nn->previous=n1;
end=nn;
}else{
start=nn;
end=nn;
}
if((*(s+1)=='s' || *(s+1)=='S') && (*(s+2)=='c' || *(s+2)=='C') && (*(s+3)=='r' || *(s+3)=='R') && (*(s+4)=='i' || *(s+4)=='I') && (*(s+5)=='p' || *(s+5)=='P') && (*(s+6)=='t' || *(s+6)=='T')){
i4=1;
}
if((*(s+1)=='s' || *(s+1)=='S') && (*(s+2)=='t' || *(s+2)=='T') && (*(s+3)=='y' || *(s+3)=='Y') && (*(s+4)=='l' || *(s+4)=='L') && (*(s+5)=='e' || *(s+5)=='E') ){
i4=1;
}
count++;
}
}
if(*s=='>'){
if(i1==0 && i2==0){
i3=0;
if(i4==0){
node *n1=end;
// cout<<(long)s+2-(n1->getstart())-(long)text<<endl;
n1->setlen((long)s+1-(n1->getstart())-(long)text);
}
if(stricmp(strlwr(end->tagname()),"script")==0){
i4=1;
}
if(stricmp(strlwr(end->tagname()),"style")==0){
i4=1;
}
}
}
if(*s=='<' && *(s+1)=='/'){
if(i1==0 && i2==0){
i3=0;
if(i4=1){
i4=0;
}
char temp[20]={0};
s=s+2;
int i=0;
while(*s!='>'){
temp[i++]=*s;
s++;
}
node *n1=end;
node* min;
while(n1!=0){
if(stricmp(n1->tagname(),temp)==0 && strlen(n1->nodehtml())==n1->getlen()){
min=n1;
break;
// cout<<min->getstart()<<"*"<<i<<endl;
}
n1=n1->previous;
}
n1=min;
// cout<<strlen(n1->nodehtml())<<"      "<<n1->getlen()<<endl;
// cout<<(long)s-(long)text-n1->getstart()<<endl;
n1->setlen((long)s+1-(n1->getstart())-(long)text);
}
}
s++;
}
}
void node::setname(char *str){
memset(name,0,20);
int i=0;
while(1){
if(*str=='!'){
name[0]='!';
break;
}else if(*str==' ' || *str=='/' || *str=='>'){
break;
}else if(*str==13 || *str==10){
break;
}else{
name[i++]=*str;
str++;
}
}
}
node *node::getparent(){
int p=-1;
for(int i=0;i<d->getcount();i++){
if(d->getitem(i)->getstart()<start){
if(d->getitem(i)->getlen()+d->getitem(i)->getstart()>start+len){
p=i;
}
}else{
break;
}
}
if(p==-1){
return 0;
}else{
return d->getitem(p);
}
}
nodecollect* node::getchild(){
int p=-1;
nodecollect *nn=new nodecollect;
for(int i=0;i<d->getcount();i++){
if(d->getitem(i)->getstart()>start){
p=i;
break;
}
}
if(p!=-1){
for(;p<d->getcount();p++){
if(start+len>d->getitem(p)->getlen()+d->getitem(p)->getstart()){
nn->add(d->getitem(p));
}else{
break;
}
}
}
return nn;
}
nodecollect* node::getbytagname(char *tagname){
nodecollect *nn=new nodecollect;
nodecollect *nn1=getchild();
for(int i=0;i<nn1->getlength();i++){
if(stricmp(nn1->item(i)->tagname(),tagname)==0){
nn->add(nn1->item(i));
}
}
return nn;
}
char *node::tagname(){
return name;
}
void node::setstart(int i){
start=i;
}
void node::setlen(int i){
len=i;
}
int node::getstart(){
return start;
}
int node::getlen(){
return len;
}
char *node::nodehtml(){
char *out=outerhtml();
int i=0,i1=0,i2=0;
char *v=new char[strlen(out)+1];
::memset(v,0,strlen(out)+1);
while(*out!=0){
if(*out==0){
return v;
}
if(*out=='\"' && *(out-1)!='\\'){
if(i1==0){
i1=1;
}else{
i1=0;
}
}
if(*out=='\'' && *(out-1)!='\\'){
if(i2==0){
i2=1;
}else{
i2=0;
}
}
if(*out=='>'){
if(i1==0 && i2==0){
v[i]='>';
return v;
}
}
v[i++]=*(out++);
}
}
char *node::outerhtml(){
char *out=new char[len+1];
char *c=d->gettext()+start;
for(int i=0;i<len;i++){
*(out+i)=*(c+i);
}
out[len]=0;
return out;
}
char *node::getattr(char* str){
char *v=nodehtml();
char* index=v;
char *attr=new char[strlen(v)+1];
memset(attr,0,strlen(v)+1);
while(1){
index=strstr(index,str);
if(index==0){
return attr;
}else{
if((*(index-1)==' ' || *(index-1)==10 || *(index-1)==13) && *(index+strlen(str))=='='){
index=index+strlen(str)+1;
break;
}
}
index++;
}
int i1=0,i2=0;
if(*index=='\"'){
i1=1;
index++;
}
if(*index=='\''){
i2=1;
index++;
}
int i=0;
while(*index!=0){
if(*index==0){
return attr;
}
if(*index=='\"' && *(index-1)!='\\'){
if(i1==0){
i1=1;
}else{
i1=0;
}
}
if(*index=='\'' && *(index-1)!='\\'){
if(i2==0){
i2=1;
}else{
i2=0;
}
}
if(*index==' ' || *index=='>' || *index=='/'){
if(i1==0 && i2==0){
if(*(index-1)=='\'' || *(index-1)=='\"'){
attr[strlen(attr)-1]=0;
return attr;
}else{
return attr;
}
}
}
*(attr+(i++))=*(index++);
}
}
char *node::innerhtml(){
char* out=outerhtml();
char *base=out;
int l=strlen(out);
int i1=0,i2=0;
char *inner=new char[strlen(out)+1];
::memset(inner,0,strlen(out)+1);
while(*out!=0){
if(*out==0){
return inner;
}
if(*out=='\"'){
if(i1==0){
i1=1;
}else{
i1=0;
}
}
if(*out=='\''){
if(i2==0){
i2=1;
}else{
i2=0;
}
}
if(*out=='>'){
if(i1==0 && i2==0){
break;
}
}
out++;
}
int innerlen=l-(strlen(tagname())+3)-(out-base+1);
if(innerlen==0){
return inner;
}else{
for(int i=0;i<innerlen;i++){
inner[i]=*(out+i+1);
}
return inner;
}
}
char *node::innertext(){
char *h=innerhtml();
char *h1=h;
char *inner;
if(h[0]==0){
inner=new char;
*inner=0;
return inner;
}else if(stricmp(strlwr(this->tagname()),"script")==0){
inner=new char[strlen(h)+1];
strcpy(inner,h);
return inner;
}else{
inner=new char[strlen(h)+1];
::memset(inner,0,strlen(h)+1);
}
int i=0,i1=0,i2=0,i3=0;
for(;*h!=0;h++){
if(*h==0){
return inner;
}
if(*h=='<'){
if(i3==0){
if((*(h+1)=='s' || *(h+1)=='S') && (*(h+2)=='c' || *(h+2)=='C') && (*(h+3)=='r' || *(h+3)=='R') && (*(h+4)=='i' || *(h+4)=='I') && (*(h+5)=='p' || *(h+5)=='P') && (*(h+6)=='t' || *(h+6)=='T')){
int l=start+strlen(nodehtml())+(h-h1);
for(int i1=0;i1<d->getcount();i1++){
if(d->getitem(i1)->getstart()==l){
strcat(inner,d->getitem(i1)->innertext());
h=h+strlen(d->getitem(i1)->outerhtml());
i=i+strlen(d->getitem(i1)->innertext());
i3=0;
break;
}
}
}else{
i3=1;
}
}
}
if(i3==1){
if(*h=='/"' && *(h-1)!='//'){
if(i1==0){
i1=1;
}else{
i1=0;
}
}
if(*h=='\'' && *(h-1)!='\\'){
if(i2==0){
i2=1;
}else{
i2=0;
}
}
if(*h=='>'){
if(i1==0 && i2==0){
i3=0;
}
}
}else{
//cout<<*h;
*(inner+i)=*h;
i++;
}
}
return inner;
}
node* node::getprevious(){
node *nn=0;
for(int i=0;i<d->getcount();i++){
if(d->getitem(i)->getstart()==start && d->getitem(i)->getlen()==len){
break;
}else{
if(start>=d->getitem(i)->getstart()+d->getitem(i)->getlen()){
nn=d->getitem(i);
}
}
}
return nn;
}
node* node::getnext(){
node *nn=0;
for(int i=0;i<d->getcount();i++){
if(start+len<=d->getitem(i)->getstart()){
nn=d->getitem(i);
break;
}
}
return nn;
}
nodecollect::nodecollect(){
n=0;
length=0;
}
int nodecollect::getlength(){
return length;
}
node *nodecollect::item(int i){
node* n1=n;
while(i--){
if(n1){
n1=n1->next;
}else{
return 0;
}
}
return n1;
}
void nodecollect::add(node *nn){
node *n1=new node;
n1->setstart(nn->getstart());
n1->setlen(nn->getlen());
n1->next=0;
char *temp=new char[strlen(nn->tagname())+2];
strcpy(temp,nn->tagname());
n1->setname(strcat(temp," "));
delete[] temp;
n1->d=nn->d;
if(n){
node *n2=n;
while(n2->next){
n2=n2->next;
}
n2->next=n1;
}else{
n=n1;
}
length++;
}
nodecollect::~nodecollect(){
node *n1=n,*n2;
if(n1){
while(n1->next!=0){
n2=n1;
n1=n1->next;
delete n2;
}
}
}


 

上面是头文件以及实现接口,下面给出个实例:

main(){
 dom d;
 d.load("<body>wef<script d=sd>gh</script>1'<img id=we/>sx<a>df<script d='d'>'<a></a>'1>22<3</script></body>");
 // for(int i=0;i<d.getcount();i++){
 cout<<d.getbyid("we")->outerhtml()<<endl;
 // }
}

       有什么不足之处,还望大家多多指正。

这篇关于完善自己的html parse的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/766961

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

HTML提交表单给python

python 代码 from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)@app.route('/')def form():# 渲染表单页面return render_template('./index.html')@app.route('/submit_form',

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密