/// <summary>
/// 对由爬虫爬取的职位类xml文件进行批量格式化(去除非打印字符,提取有用节点)并拼接成一个xml文件,方便数据库或Excel导入。
/// </summary>
class XMLCombine
{
private string SavePath { get; set; }//拼接后的xml文件保存或加载路径(包括文件名)
private XDocument XML { get; set; }//将指定路径的xml加载进XDocument类。
public XMLCombine(string savePath)
{
this.SavePath = savePath;
if (!File.Exists(savePath))
{
XDocument xWrite = new XDocument();
XElement xJobs = new XElement("Jobs");
xWrite.Add(xJobs);
xWrite.Save(savePath);//创建xml文件
}
this.XML = XDocument.Load(savePath);
}
/// <summary>
/// 对由招聘网站爬取的分页的职位列表-xml文件进行字段提取,合并。
/// </summary>
/// <param name="path">批量导入的xml文件所在的目录</param>
/// <param name="posts">需要从xml文件中提取的字段(节点)</param>
/// <param name="rTF">准备导入的xml文件的编码格式</param>
/// <returns>文本形式保存的新增/修改的职位数和对新xml文件导入时的查重</returns>
public string AddNewPost(string path, string posts, Encoding rTF)
{
int countAdd = 0;//新增/更新的职位数
int countRepeat1 = 0;//新导入的xml文件中的职位重复数。
int countRepeat2 = 0;//新导入的职位信息与原已拼接的xml文件的职位重复数
Dictionary<string, XElement> selectInfo = new Dictionary<string, XElement>();//key为职位主页的网址(作为查重依据),value为以单个职位信息作为的节点
string[] thisPosts = posts.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
IEnumerable<string> filesEnum = Directory.EnumerateFiles(path, "*.xml");//遍历指定文件夹下的xml文件
IEnumerator<string> paths = filesEnum.GetEnumerator();
while (paths.MoveNext())
{
string str = File.ReadAllText(paths.Current, rTF);
StringBuilder sb = new StringBuilder();
foreach (char cc in str)//将xml对象中包含的低序位非打印 ASCII 字符去除,以免XDocment读取异常
{
int ss = (int)cc;
if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
{ sb.AppendFormat(" ", ss); }
else { sb.Append(cc); }
}
str = sb.ToString();
XDocument readXdoc = XDocument.Parse(str);//将格式化后的字符串创建为XDocment对象
//DescendantsAndSelf(XName):从XElements集合的的所有元素及其子代元素中查找指定XName的元素,返回第一个。
XElement jobInfos = readXdoc.Elements().DescendantsAndSelf("职位信息").First();
foreach (XElement jobInfo in jobInfos.Elements())
{
XElement newJob = new XElement("Person");
for (int i = 0; i < thisPosts.Length; i++)
{
string name = thisPosts[i];
XElement xel = jobInfo.Element(name);//检索子元素下指定名称的第一个元素(节点)
//去除多余的空字符和换行符
string temp = string.Join(" ", xel.Value.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
string value = string.Join("\n", temp.Split(new string[] { "\n ", " \n", "\n" }, StringSplitOptions.RemoveEmptyEntries));
newJob.SetElementValue(name, value);
}
string webSite = newJob.Element("网址").Value;
if (!selectInfo.ContainsKey(webSite))
{
selectInfo.Add(webSite, newJob);//将格式化并查重后的每个职位信息存入字典,以职位主页网址为索引
countAdd++;
}
else countRepeat1++;
}
}
XElement oldRoot = this.XML.Root;
foreach (XElement item in oldRoot.Elements())
{
string selectWebSite = item.Element("网址").Value;
//变量原已拼接的xml文件中的职位,判断每个职位的网址是否与字典中职位的网站相同,如果是,则去除字典中的重复职位,将剩余不重复的加入xml文件中
if (selectWebSite!=null&&selectInfo.ContainsKey(selectWebSite))
{
selectInfo.Remove(selectWebSite);//从字典中移除指定Key的元素
countRepeat2++;
}
}
oldRoot.Add(selectInfo.Values);
this.XML.Save(this.SavePath);
countAdd = countAdd - countRepeat2;
return "新增职位数:" + countAdd + ",准备导入的批量xml之中的职位重复数:" + countRepeat1 + ",准备导入的批量xml与原保存的xml数据中的重复职位数:" + countRepeat2;
}
/// <summary>
/// 对由爬虫从招聘网站爬取的每个职位主页信息进行格式化(去除非打印字符,提取有用节点),拼接进包含职位列表的xml文件,方便数据库或Excel导入。
/// </summary>
/// <param name="path">批量导入的xml文件所在的目录</param>
/// <param name="represents">需要从xml文件中提取的字段(节点:职位信息)</param>
/// <param name="rTF">准备导入的xml文件的编码格式</param>
/// <returns>文本形式保存的新增/修改的职位数和对新xml文件导入时的查重</returns>
public string AddNewRepresent(string path, string represents, Encoding rTF)
{
int countAdd = 0;
int countRepeat1 = 0;
int countRepeat2 = 0;
Dictionary<string, XElement> selectInfo = new Dictionary<string, XElement>();
string[] thisRepresents = represents.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); ;
IEnumerable<string> filesEnum = Directory.EnumerateFiles(path, "*.xml");
IEnumerator<string> paths = filesEnum.GetEnumerator();
while (paths.MoveNext())
{
string str = File.ReadAllText(paths.Current, rTF);
StringBuilder info = new StringBuilder();
foreach (char cc in str)
{
int ss = (int)cc;
if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
info.AppendFormat(" ", ss);
else info.Append(cc);
}
str = info.ToString();
XDocument xml = XDocument.Parse(str);
XElement xPerson = new XElement("Person");
for (int i = 0; i < thisRepresents.Length; i++)
{
string name = thisRepresents[i];
XElement xel = xml.Root.DescendantsAndSelf(name).First();
string temp = string.Join(" ", xel.Value.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
string value = string.Join("\n", temp.Split(new string[] { "\n ", " \n", "\n" }, StringSplitOptions.RemoveEmptyEntries));
//招聘部门这个字段中,默认包含了“企业名+部门”,将企业名去除。
if (name == "招聘部门")
{
value = value.Replace(xml.Root.DescendantsAndSelf("企业名").First().Value.Trim(), "");
}
xPerson.SetElementValue(name, value);//将获取的节点格式化后(去除空字符)写入新的XDocment对象下
}
//职位主页的网址在fullpath这个字段中。
string webSite = xml.Root.DescendantsAndSelf("fullpath").First().Value.Trim();
if (!selectInfo.ContainsKey(webSite))
{
selectInfo.Add(webSite, xPerson);
}
else countRepeat1++;
}
XElement oldRoot = this.XML.Root;
foreach (XElement item in oldRoot.Elements())
{
string selectWebSite = item.Element("网址").Value;
XElement addInfo = selectInfo[selectWebSite];
//遍历已拼接的xml文件中的职位,如果职位的网址与字典中的职位主页的网址相同,并且判断字典中该职位信息未加入到该xml文件中,则向xml文件添加进字典中该职位的信息
if (selectWebSite!=null&&
item.LastNode.ToString() !=addInfo.LastNode.ToString()&&
selectInfo.ContainsKey(selectWebSite))
{
item.Add(addInfo.Elements());
++countAdd;
}
else countRepeat2++;
}
this.XML.Save(this.SavePath);
return "补全职位数:" + countAdd + ",准备导入的批量xml之中的职位重复数:" + countRepeat1 + ",准备导入的批量xml与原保存的xml数据中的重复职位数:" + countRepeat2;
}
}
批量合并xml文件
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 思路描述:CodeIgniter同时添加多条数据到数据库,框架自身提供了如下方法。 $this->db->inse...
- SpringBatch Flatfile(XML,CSV,TXT) 文件的批量读写 该系列课程中的示例代码使用sp...
- 由表A到表B,同一部门名称合并,你是一次一次选中同一部门,点击“合并单元格”吗? 由表B到表A,你是取消“合并单元...