当前位置: 首页 > news >正文

安徽建网站实时热榜

安徽建网站,实时热榜,站内seo是什么意思,公司网站开发设计题目来源怎么写libxml -- 解析 XML 文档XML 介绍#xff1a;XML 和 DOMlibxml 介绍 数据类型 — xmlChar数据结构 创建 XML 文档解析 XML 文档修改 xml 文档Xpath — 处理大型 XML 文档libxml2 库函数要注意的函数读取 xml 文件xml 操作基本结构及其指针类型根节点相关函数 创建子节点相关函…libxml -- 解析 XML 文档XML 介绍XML 和 DOM libxml 介绍 数据类型 — xmlChar数据结构 创建 XML 文档解析 XML 文档修改 xml 文档 Xpath — 处理大型 XML 文档libxml2 库函数 要注意的函数读取 xml 文件xml 操作基本结构及其指针类型根节点相关函数 创建子节点相关函数添加子节点相关函数属性相关函数 参考 http://xmlsoft.org/http://www.miidoo.cn/info_detail-204.htmlhttp://www.blogjava.net/wxb_nudt/archive/2007/11/28/161340.htmlhttp://www.ibm.com/developerworks/cn/aix/library/au-libxml2.htmlhttp://www.cppblog.com/lymons/archive/2009/03/30/37553.htmlXPath 教程 XML 介绍XML 和 DOM XML是eXtensible Markup Language的缩写它是一种可扩展性标识语言, 能够让你自己创造标识标识你所表示的内容。DOM全称是Document Object Model(文档对象模型)定义了一组与平台和语言无关的接口以便程序和脚本能够动态访问和修改XML文档内容、结构及样式。XML创建了标识而 DOM的作用就是告诉程序如何操作和显示这些标识。 XML将数据组织成为一棵树DOM通过解析XML文档为XML文档在逻辑上建立一个树模型树的节点是一个个的对象。这样通过操作这棵树和这些对象就可以完成对XML文档的操作为处理文档的所有方面提供了一个完美的概念性框架。 XML 中共有12种节点类型其中最常见的节点类型有5种 元素元素是 XML 的基本组成单元。描述XML的基本信息。属性属性节点包含关于元素节点的信息通常包含在元素里面描述元素的属性。文本包含许多文本信息或者只是空白。文档文档节点是整个文档中所有其它节点的父节点。注释注释是对相关的信息进行描述、注释。 libxml 介绍 本文所介绍的 libxml 是针对 C 语言的一套 API 接口。其他如 rubypython 亦有对应的基于 libxml 开发的绑定库接口。 数据类型 — xmlChar 在 libXml 中用 xmlChar 替代 char , XML 使用 UTF-8 编码的一字节字符串。如果你的数据使用其它编码它必须被转换到 UTF-8 才能使用libxml的函数。 如同标准 C 中的 char 类型一样 xmlChar 也有动态内存分配、字符串操作等相关函数。例如 xmlMalloc 是动态分配内存的函数 xmlFree 是配套的释放内存函数 xmlStrcmp 是字符串比较函数等等。基本上 xmlChar 字符串相关函数都在xmlstring.h 中定义而动态内存分配函数在 xmlmemory.h 中定义。另外要注意因为总是要在 xmlChar* 和 char* 之间进行类型转换所以定义了一个宏 BAD_CAST 其定义如下 xmlstring.h #define BAD_CAST (xmlChar *) 原则上来说 unsigned char 和 char 之间进行强制类型转换是没有问题的。 数据结构 xmlDoc代表DOM结构中的文档类型。包含由解析文档建立的树结构 xmlDocPtr 是指向这个结构的指针。xmlNode代表DOM结构中的除文档类型类型外的其它节点类型。包含单一结点的结构 xmlNodePtr 是指向这个结构的指针它被用于遍历文档树。节点应该是xml中最重要的元素了 xmlNode 代表了xml文档中的一个节点实现为一个 struct 内容很丰富 tree.h typedef struct _xmlNode xmlNode; typedef xmlNode *xmlNodePtr; struct _xmlNode { void *_private;/* application data */ xmlElementType type; /* type number, must be second ! */ const xmlChar *name; /* the name of the node, or the entity */ struct _xmlNode *children; /* parent-childs link */ struct _xmlNode *last; /* last child link */ struct _xmlNode *parent;/* child-parent link */ struct _xmlNode *next; /* next sibling link */ struct _xmlNode *prev; /* previous sibling link */ struct _xmlDoc *doc;/* the containing document */ /* End of common part */ xmlNs *ns; /* pointer to the associated namespace */ xmlChar *content; /* the content */ struct _xmlAttr *properties;/* properties list */ xmlNs *nsDef; /* namespace definitions on this node */ void *psvi;/* for type/PSVI informations */ unsigned short line; /* line number */ unsigned short extra; /* extra data for XPath/XSLT */ }; 可以看到节点之间是以链表和树两种方式同时组织起来的next和prev指针可以组成链表而parent和children可以组织为树。所有节点都是文档 xmlDoc 节点的直接或间接子节点。同时还有以下重要元素 节点中的文字内容 content 节点所属文档 doc 节点名字 name 节点的 namespace ns 节点属性列表 properties xml 文档的操作其根本原理就是在节点之间移动、查询节点的各项信息并进行增加、删除、修改的操作。 xmlDocSetRootElement 函数可以将一个节点设置为某个文档的根节点这是将文档与节点连接起来的重要手段当有了根结点以后所有子节点就可以依次连接上根节点从而组织成为一个 xml 树。 创建 XML 文档 创建一个 XML 文档流程如下 用 xmlNewDoc 函数创建一个文档指针 doc;用 xmlNewNode 函数创建一个节点指针 root_node;用 xmlDocSetRootElement 将 root_node 设置为 doc 的根节点;给 root_node 添加一系列子节点并设置字节点的内容和属性;用 xmlSaveFile 保存 xml 到文件;用 xmlFreeDoc 函数关闭文档指针清除内存。 示例 下面用一个例子说明一些函数的使用和创建一个 XML 文档的大致步骤 #include stdio.h #include stdlib.h #include libxml/parser.h #include libxml/tree.h int main (int argc, char **argv) { xmlDocPtr pdoc NULL; xmlNodePtr proot_node NULL,pnode NULL,pnode1 NULL; // 创建一个新文档并设置 root 节点 // 一个 XML 文件只有一个 root 节点 pdoc xmlNewDoc (BAD_CAST 1.0); proot_node xmlNewNode (NULL, BAD_CAST 根节点); xmlNewProp (proot_node, BAD_CAST 版本, BAD_CAST 1.0); xmlDocSetRootElement (pdoc, proot_node); pnode xmlNewNode (NULL, BAD_CAST 子节点1); // 创建上面 pnode 的子节点 xmlNewChild (pnode, NULL, BAD_CAST 子子节点1, BAD_CAST 信息); // 添加子节点到 root 节点 xmlAddChild (proot_node, pnode); pnode1 xmlNewNode (NULL, BAD_CAST 子子节点1); xmlAddChild (pnode, pnode1); xmlAddChild (pnode1,xmlNewText (BAD_CAST 这是更低的节点,子子子节点1)); // 还可以这样直接创建一个子节点到 root 节点上 xmlNewTextChild (proot_node, NULL, BAD_CAST 子节点2, BAD_CAST 子节点2的内容); xmlNewTextChild (proot_node, NULL, BAD_CAST 子节点3, BAD_CAST 子节点3的内容); // 保存 xml 为文件,如果没有给出文件名参数就输出到标准输出 xmlSaveFormatFileEnc (argc 1 ? argv[1]:-, pdoc, UTF-8, 1); // 释放资源 xmlFreeDoc (pdoc); xmlCleanupParser (); xmlMemoryDump (); return 0; } 编译这个例子先看看系统里面的 libxml2 库的 pkgconfig 信息 rootjianlee:~/lab/xml# cat /usr/lib/pkgconfig/libxml-2.0.pc prefix/usr exec_prefix${prefix} libdir${exec_prefix}/lib includedir${prefix}/include modules1 Name: libXML Version: 2.6.32 Description: libXML library version2. Requires: Libs: -L${libdir} -lxml2 Libs.private: -lz -lm Cflags: -I${includedir}/libxml2 rootjianlee:~/lab/xml# pkg-config libxml-2.0 --cflags --libs -I/usr/include/libxml2 -lxml2 编译 rootjianlee:~/lab/xml# gcc -Wall pkg-config libxml-2.0 --cflags --libs create_xml.c 如果没有修改源程序输出应该是这样 rootjianlee:~/lab/xml# ./a.out ?xml version1.0 encodingUTF-8? 根节点 版本1.0 子节点1 子子节点1信息/子子节点1 子子节点1这是更低的节点,子子子节点1/子子节点1 /子节点1 子节点2子节点2的内容/子节点2 子节点3子节点3的内容/子节点3 /根节点 示例补充说明 输出的各节点不要在一行 上面使用下面方式保存 xml 文档输出的文件各子节点间自动加入回车 // 保存 xml 为文件,如果没有给出文件名参数就输出到标准输出 xmlSaveFormatFileEnc (argc 1 ? argv[1]:-, pdoc, UTF-8, 1); 如果把上面的 1 换成 0 输出格式是放在一行。 用到的函数说明 上面涉及几个函数和类型定义不过意思很明了下面解释一个重要的是自己动手写程序反复实验所谓熟能生巧。 xmlDocPtr指向 XML 文档对象的指针xmlNodePtr指向 XML 文档对象中的节点对象根节点和子节点都是一样的xmlNewDoc创建一个 XML 文档对象xmlNewNode创建一个 XML 文档的指针对象xmlNewProp给一个节点增加属性信息包括在 中如 xmlNewProp (proot_node, BAD_CAST 版本, BAD_CAST 1.0); 最后显示是这个样子 根节点 版本1.0 xmlDocSetRootElement设置 XML 文档对象的根节点只有一个根节点xmlNewChild指定一个节点会创建这个节点的子节点。这样不需要使用 xmlNewNode 创建一个节点再使用 xmlAddChild 添加到其父节点中。xmlAddChild把一个节点设置为另外一个节点的子节点。xmlNewText创建一个描述节点没有 符号需要添加到其他节点上。比如上例中的 xmlAddChild (pnode1,xmlNewText (BAD_CAST 这是更低的节点,子子子节点1)); 会出现下面的结果 子子节点1这是更低的节点,子子子节点1/子子节点1 xmlNewTextChild和 xmlNewText 的区别如同 xmlNewNodeChild 和 xmlNewNode 的区别一样xmlSaveFormatFileEnc保存 xml 对象为文件。xmlFreeDoc释放 xml 对象xmlCleanupParser清理xmlMemoryDump清理 解析 XML 文档 解析一个xml文档从中取出想要的信息例如节点中包含的文字或者某个节点的属性其流程如下 用 xmlReadFile 函数读出一个文档指针 doc 用 xmlDocGetRootElement 函数得到根节点 curNode curNode-xmlChildrenNode 就是根节点的子节点集合 轮询子节点集合找到所需的节点用 xmlNodeGetContent 取出其内容 用 xmlHasProp 查找含有某个属性的节点 取出该节点的属性集合用 xmlGetProp 取出其属性值 用 xmlFreeDoc 函数关闭文档指针并清除本文档中所有节点动态申请的内存。 注意 节点列表的指针依然是 xmlNodePtr 属性列表的指针也是 xmlAttrPtr 并没有 xmlNodeList 或者 xmlAttrList 这样的类型 。看作列表的时候使用它们的 next 和 prev 链表指针来进行轮询 。只有在 Xpath 中有 xmlNodeSet 这种类型。 示例 #include stdio.h #include stdlib.h #include libxml/parser.h #include libxml/tree.h int main (int argc , char **argv) { xmlDocPtr pdoc NULL; xmlNodePtr proot NULL, curNode NULL; char *psfilename; if (argc 1) { printf (用法: %s xml文件名\n, argv[0]); exit (1); } psfilename argv[1]; // 打开 xml 文档 //xmlKeepBlanksDefault(0); pdoc xmlReadFile (psfilename, UTF-8, XML_PARSE_RECOVER); if (pdoc NULL) { printf (打开文件 %s 出错!\n, psfilename); exit (1); } // 获取 xml 文档对象的根节对象 proot xmlDocGetRootElement (pdoc); if (proot NULL) { printf(错: %s 是空文档没有root节点\n, psfilename); exit (1); } /* 我使用上面程序创建的 xml 文档它的根节点是“根节点”这里比较是否 正确。*/ if (xmlStrcmp (proot-name, BAD_CAST 根节点) ! 0) { printf (错误文档 ); exit (1); } /* 如果打开的 xml 对象有 version 属性那么就输出它的值。 */ if (xmlHasProp (proot, BAD_CAST 版本)) { xmlChar *szAttr xmlGetProp (proot, BAD_CAST 版本); printf (版本: %s \n根节点%s\n , szAttr, proot-name); } else { printf ( xml 文档没有版本信息\n); } curNode proot-xmlChildrenNode; char n0; while (curNode ! NULL) { if (curNode-name ! BAD_CAST text) { printf (子节点%d %s\n, n,curNode-name); } curNode curNode-next; } /* 关闭和清理 */ xmlFreeDoc (pdoc); xmlCleanupParser (); return 0; } 编译运行使用上例创建的 my.xml 文件 rootjianlee:~/lab/xml# cat my.xml ?xml version1.0 encodingUTF-8? 根节点 版本1.0 子节点1 子子节点1信息/子子节点1 子子节点1这是更低的节点,子子子节点1/子子节点1 /子节点1 子节点2子节点2的内容/子节点2 子节点3子节点3的内容/子节点3 /根节点 rootjianlee:~/lab/xml# gcc -Wall pkg-config libxml-2.0 --cflags --libs read_xml.c rootjianlee:~/lab/xml# ./a.out my.xml 版本: 1.0 根节点根节点 子节点0 text 子节点1 子节点1 子节点2 text 子节点3 子节点2 子节点4 text 子节点5 子节点3 子节点6 text 为什么 my.xml 文件中显示只有 ”子节点1“、 ”子节点2“和 “子节点3”三个子节点而程序显示有 7 个子节点呢而且 0、2、4、6 都是 text 名字 这是因为其他四个分别是元素前后的空白文本符号而 XML 把它们也当做一个 Node 元素是 Node 的一种类型。XML 文档对象模型 (DOM) 定义了几种不同的 Nodes 类型包括 Elements如 files 或者 age、Attributes如 units和 Text如 root 或者 10。元素可以具有子节点。 在打开 xml 文档之前加上一句取消上面程序中的此句注释就可以 xmlKeepBlanksDefault(0); 或者使用下面参数读取 xml 文档 //读取xml文件时忽略空格 doc xmlReadFile(docname, NULL, XML_PARSE_NOBLANKS); 这样就可以按我们所想的运行了 rootjianlee:~/lab/xml# gcc -Wall pkg-config libxml-2.0 --cflags --libs read_xml.c rootjianlee:~/lab/xml# ./a.out my.xml 版本: 1.0 根节点根节点 子节点0 子节点1 子节点1 子节点2 子节点2 子节点3 还有一点注意 my.xml 文件中的子节点名字一次是 “子节点1”、“子节点2”、 “子节点3”。程序中的 n 值确是从 0 开始计算。从 0 还是 1 是个人喜好。我有时候喜好从 0 开始有时候喜好从 1 开始。 xmlFreeDoc释放文档指针。特别注意当你调用 xmlFreeDoc 时该文档所有包含的节点内存都被释放所以一般来说不需要手动调用 xmlFreeNode 或者 xmlFreeNodeList 来释放动态分配的节点内存除非你把该节点从文档中移除了。一般来说一个文档中所有节点都应该动态分配然后加入文档最后调用 xmlFreeDoc 一次释放所有节点申请的动态内存这也是为什么我们很少看见 xmlNodeFree 的原因。xmlSaveFile将文档以默认方式存入一个文件。xmlSaveFormatFileEnc可将文档以某种编码/格式存入一个文件中,创建 xml 文档是的示例中用到 修改 xml 文档 首先打开一个已经存在的xml文档顺着根结点找到需要添加、删除、修改的地方调用相应的xml函数对节点进行增、删、改操作。 删除节点 删除节点使用下面方法 if (!xmlStrcmp(curNode-name, BAD_CAST newNode1)) { xmlNodePtr tempNode; tempNode curNode-next; xmlUnlinkNode(curNode); xmlFreeNode(curNode); curNode tempNode; continue; } 即将当前节点从文档中断链unlink这样本文档就不会再包含这个子节点。这样做需要使用一个临时变量来存储断链节点的后续节点并记得要手动删除断链节点的内存。 示例 #include stdio.h #include stdlib.h #include libxml/parser.h int main(int argc, char* argv[]) { xmlDocPtr doc; //定义解析文档指针 xmlNodePtr curNode; //定义结点指针(你需要它为了在各个结点间移动) char *szDocName; if (argc 1) { printf(Usage: %s docname\n, argv[0]); return(0); } szDocName argv[1]; xmlKeepBlanksDefault(0); doc xmlReadFile(szDocName,UTF-8,XML_PARSE_RECOVER); //解析文件 if (NULL doc) { fprintf(stderr,Document not parsed successfully. \n); return -1; } curNode xmlDocGetRootElement(doc); /*检查确认当前文档中包含内容*/ if (NULL curNode) { fprintf(stderr,empty document\n); xmlFreeDoc(doc); return -1; } curNode curNode-children; while (NULL ! curNode) { //删除 子节点1 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点1)) { xmlNodePtr tempNode; tempNode curNode-next; xmlUnlinkNode(curNode); xmlFreeNode(curNode); curNode tempNode; continue; } //修改 子节点2 的属性值 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点2)) { xmlSetProp(curNode,BAD_CAST 属性1, BAD_CAST 设置); } //修改 “子节点2” 的内容 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点2)) { xmlNodeSetContent(curNode, BAD_CAST 内容变了); } //增加一个属性 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点3)) { xmlNewProp(curNode, BAD_CAST 新属性, BAD_CAST 有); } //增加 子节点4 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点3)) { xmlNewTextChild(curNode, NULL, BAD_CAST 新子子节点1, BAD_CAST 新内容); } curNode curNode-next; } // 保存文件 xmlSaveFormatFileEnc (szDocName, doc,UTF-8,1); xmlFreeDoc (doc); xmlCleanupParser (); xmlMemoryDump (); return 0; } 编译运行 rootjianlee:~/lab/xml# cat my.xml ?xml version1.0 encodingUTF-8? 根节点 版本1.0 子节点1 子子节点1信息/子子节点1 子子节点1这是更低的节点,子子子节点1/子子节点1 /子节点1 子节点2子节点2的内容/子节点2 子节点3子节点3的内容/子节点3 /根节点 rootjianlee:~/lab/xml# gcc -Wall pkg-config libxml-2.0 --cflags --libs modify_xml.c rootjianlee:~/lab/xml# ./a.out my.xml rootjianlee:~/lab/xml# cat my.xml ?xml version1.0 encodingUTF-8? 根节点 版本1.0 子节点2 属性1设置内容变了/子节点2 子节点3 新属性有子节点3的内容新子子节点1新内容/新子子节点1/子节点3 /根节点 rootjianlee:~/lab/xml# ./a.out my.xml # 看看再运行一次的结果 rootjianlee:~/lab/xml# cat my.xml ?xml version1.0 encodingUTF-8? 根节点 版本1.0 子节点2 属性1设置内容变了/子节点2 子节点3 新属性有 新属性有子节点3的内容新子子节点1新内容/新子子节点1新子子节点1新内容/新子子节点1/子节点3 /根节点 Xpath — 处理大型 XML 文档 libxml2 库函数 要注意的函数 xmlKeepBlanksDefault int xmlKeepBlanksDefault (int val) 设置是否忽略空白节点,比如空格,在分析前必须调用,默认值是0,最好设置成1. xmlKeepBlanksDefault(0) 除了在读入xml文件时忽略空白之外还会在写出xml 文件时在每行前面放置缩进indent。如果使用xmlKeepBlanksDefault(1) 则你会发现每行前面的缩进就没有了但不会影响回车换行。 xmlSaveFormatFile // 保存 xml 为文件,如果没有给出文件名参数就输出到标准输出 xmlSaveFormatFileEnc (argc 1 ? argv[1]:-, pdoc, UTF-8, 1); xmlSaveFormatFile 的 format 参数设置成 0保存后的 xml 文档里是会把所有的结点都放到一行里显示。设置为 1,就可以自动添加回车。 读取 xml 文件 xmlParseFile xmlDocPtr xmlParseFile (const char * filename) 以默认方式读入一个 UTF-8 格式的 xml 文档, 并返回一个文档对象指针 libxml/tree.h xmlReadFile 指定编码读取一个 xml 文档返回指针。 xml 操作基本结构及其指针类型 xmlDoc, xmlDocPtr 文档对象的结构体及其指针 xmlNode, xmlNodePtr 节点对象的结构体及其指针 xmlAttr, xmlAttrPtr 节点属性的结构体及其指针 xmlNs, xmlNsPtr 节点命名空间的结构及其指针 根节点相关函数 xmlDocGetRootElement xmlNodePtr xmlDocGetRootElement (xmlDocPtr doc) 获取文档根节点 xmlDocSetRootElement xmlNodePtr xmlDocSetRootElement (xmlDocPtr doc, xmlNodePtr root) 设置文档根节点 创建子节点相关函数 xmlNewNode xmlNodePtr xmlNewNode (xmlNsPtr ns, const xmlChar * name) 创建新节点 xmlNewChild xmlNodePtr xmlNewChild (xmlNodePtr parent, xmlNsPtr ns, const xmlChar * name, const xmlChar * content) 创建新的子节点 xmlCopyNode xmlNodePtr xmlCopyNode (const xmlNodePtr node, int extended) 复制当前节点 添加子节点相关函数 xmlAddChild xmlNodePtr xmlAddChild (xmlNodePtr parent, xmlNodePtr cur) 给指定节点添加子节点 xmlAddNextSibling xmlNodePtr xmlAddNextSibling (xmlNodePtr cur, xmlNodePtr elem) 添加后一个兄弟节点 xmlAddPrevSibling xmlNodePtr xmlAddPrevSibling (xmlNodePtr cur, xmlNodePtr elem) 添加前一个兄弟节点 xmlAddSibling xmlNodePtr xmlAddSibling (xmlNodePtr cur, xmlNodePtr elem) 添加兄弟节点 属性相关函数 xmlNewProp xmlAttrPtr xmlNewProp (xmlNodePtr node, const xmlChar * name, const xmlChar * value) 创建新节点属性 xmlGetProp xmlChar * xmlGetProp (xmlNodePtr node, const xmlChar * name) 读取节点属性 xmlSetProp xmlAttrPtr xmlSetProp (xmlNodePtr node, const xmlChar * name, const xmlChar * value) 设置节点属性
http://www.huolong8.cn/news/114878/

相关文章:

  • 怎么建设域名和网站彩票网站招代理广告怎么做
  • 免费海报在线制作网站麻章网站建设公司
  • 网站h标签网站系统方案设计
  • 模板建站优缺点windows2012做网站
  • 仙游县住房和城乡建设局网站市场营销考研可以考哪些专业
  • 手机网站开发步骤软件wordpress新网站
  • 个人网站免费模板网站做多个镜像
  • 商家在携程旅游网站怎样做宣传网站建设方案范文1000字
  • 电子商务网站开发合同qq代刷网站社区建设
  • 昆山建设局图审中心网站溧阳做网站哪家好
  • 杭州有没有专业做网站的公司wordpress怎么上传插件
  • 网站工商备案查询网页制作教程和流程
  • 新蔡县住房和城乡建设局网站网站建设需要配置环境么
  • 遵义网站建设制作公司如何建立网站服务器
  • 建立网站策划科技与狠活
  • 如何在eclipse上做网站沈阳工伤保险做实网站
  • 云南网站建设是什么电商平台营销策划方案
  • 学校做网站青羊区建设和交通网站
  • 珠海网站设计如何做输入密码进入网站
  • 可以做系统同步时间的网站网站建设需要考虑什么因素
  • 做五金有哪些网站推广网站包括哪些内容
  • 怎样才能做好网站优化全国十大计算机培训机构
  • python可以做网站后台吗如何做网站淘宝客
  • 新乡营销网站建设中小企业网络规划与设计论文
  • 免费学设计的网站网站模板上传工具
  • 做视频网站用哪个软件好做交易网站需要办什么证
  • 做网站和APP需要多少钱wordpress 主题版权
  • 我想建个自己的网站做国际网站怎么能快速打开
  • 医院网站建设多少钱中国城乡建设部官网
  • 网站做引流外贸求购信息网