作者:一只尼玛
链接:https://www.zhihu.com/question/25052291/answer/107829888
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我来回答这个弱智的问题。
什么是xml,什么是excel?
她们两种都是一种文件格式,属于文本文件。计算机里面要存放数据,一般都是存放在文件中,有些是文本文件,有些是二进制文件,比如图片是二进制文件,你用文本编辑器打开会看到乱码,而一些文件打开,你大致读得懂就是文本文件。数据库存放的数据底层也是存放在文件里面。
好!xml是一种扩展标记语言,是html的超集,具体请百度。你可自己定义标记,比如<爱我>才怪</爱我>,哈哈哈哈,大致是这样。这样的文本文件有层次结构,熟称文档对象模型DOM,或者直接叫文档树,有父母,兄弟,儿子,孙子等。这种格式的产生是为了数据的传输,因为http协议,一般我们做网站的时候要传数据,xml就是一种很好的选择,因为便于提取,虽然现在大部分已经用json了。我就不展开了,也可以把这个问题改为,怎样将json批量导入excel?
为什么要将数据导入到excel?
现在你要提取到excel,就是说你想整理这些数据,因为excel的功能就是简单化数据处理,而不需要手动编程。。。你要提取爱我,才怪,这些你喜欢的标记里面的内容或者属性,便于统计整理。直接在文本编辑器编辑是不可能的,因为你打开xml文件是很难整理的。
而excel文件有个excel软件在支持它,因为excel就像小型的数据库,有行列嘛,想想access,然后还有mysql数据库,现在的mongo db,redis等,其实就是一个数据的存储地,但是有了一些其它的功能。。
如何导入excel?
切入正题,来回答乎主的问题。怎么把xml提取到excel?
嗯,写程序就行了。可以用Vb写,这样打开excel运行宏就行了,不过数据量一大就会特别慢。有一个懒人爬虫软件及搜客就经常有这种xml转excel的需求,因为设计者当初把数据传输格式定为xml,所以有一班不是很专业,又很专业的人,写了一些Vb程序,还行。
但是,用JAVA,Go,Python解析xml是特别容易的,而且速度快。
程序演示
我已经写好了一个软件,请上github寻找:GitHub - hunterhug/xmlmerge: 及搜客XML合并程序 这个程序已经封装成exe在Windows下可以直接运行。我来演示一下操作。
注意,这个程序只能处理及授课软件生成的xml,有格式要求!!!
注意,这个程序只能处理及授课软件生成的xml,有格式要求!!!
注意,这个程序只能处理及授课软件生成的xml,有格式要求!!!
这是程序目录结构
-- exerun5.0 运行目录<br /> -- xmlchange.exe 可执行文件<br /> -- files 需处理的XML(递归子文件夹)<br /> -- jingjie_详情_175894040_1117385545.xml<br /> -- jingjie_详情_175894040_111738554f.xml<br /> -- jingjie_详情_1758940s_1117385545.xml<br /> -- source 源程序<br /> -- xmlchange.py 源代码<br /> -- setup.py 打包配置<br /> --run.bat 批处理运行脚本 -- data 演示数据<br />
使用方式
&amp;amp;amp;amp;amp;amp;lt;img data-rawheight="502" data-rawwidth="588" src="//pic.ikafan.com/imgp/L3Byb3h5L2h0dHBzL3BpYzEuemhpbWcuY29tL2FlZDQzZTQ3ZTAxMWI5YzNlMWVkNjdlZGQxOTc0NGMwX2IucG5n.jpg" class="origin_image zh-lightbox-thumb" width="588" data-original="https://pic1.zhimg.com/aed43e47e011b9c3e1ed67edd19744c0_r.png"&amp;amp;amp;amp;amp;amp;gt;
xml格式是由及搜客懒人软件生成的,格式如下:
&amp;amp;amp;amp;amp;amp;lt;img data-rawheight="516" data-rawwidth="1096" src="//pic.ikafan.com/imgp/L3Byb3h5L2h0dHBzL3BpYzQuemhpbWcuY29tLzI5ZGQ0MTdmOGM5NDA2MDc3YTI0ZDUyNmNlNGRlYjY3X2IucG5n.jpg" class="origin_image zh-lightbox-thumb" width="1096" data-original="https://pic4.zhimg.com/29dd417f8c9406077a24d526ce4deb67_r.png"&amp;amp;amp;amp;amp;amp;gt;
格式必须满足:
<?xml version="1.0" encoding="UTF-8"?> <root> <clueid>177304011</clueid> <createdate>2015-11-27 14:10:33</createdate> <uri><![CDATA[https://list.tmall.hk/search_product.htm?cat=52792006&s=60&q=%B0%C4%D6%DE&sort=s&style=g&auction_tag=13186;&from=tmallhk.list.pc_1_suggest&suggest=0_3&spm=a2231.7718719.a2227oh.d100&tmhkmain=1&type=pc#J_Filter]]></uri> <item><标题>澳洲直邮 悉尼发货 Woolworths 全脂高钙成人奶粉 1kg</标题></item> <item><标题>澳洲直邮 悉尼发货 Woolworths 全脂高钙成人奶粉 1kg</标题></item> <item><标题>澳洲直邮 悉尼发货 Woolworths 全脂高钙成人奶粉 1kg</标题></item> </root>
必须有有一个根元素包裹所有的子元素,然后必须有<clueid><createdate><uri>三个子元素,数据则是在<item>中。<iitem>中可以嵌套<item>但是模式需要有重复,否则excel里面会乱版。
好丑,哈哈哈哈,然后运行程序。
&amp;amp;amp;amp;amp;amp;lt;img data-rawheight="537" data-rawwidth="642" src="//pic.ikafan.com/imgp/L3Byb3h5L2h0dHBzL3BpYzIuemhpbWcuY29tLzNjZGZjMWRiZWJiN2NhOGU0ZjdiNmRjZDFmNmU4MjAxX2IucG5n.jpg" class="origin_image zh-lightbox-thumb" width="642" data-original="https://pic2.zhimg.com/3cdfc1dbebb7ca8e4f7b6dcd1f6e8201_r.png"&amp;amp;amp;amp;amp;amp;gt;
生成了一个excel文件,这个处理的速度特别快,达到多快,麻烦大家帮我测试一下,或者有什么bug也可以提出。
&amp;amp;amp;amp;amp;amp;lt;img data-rawheight="535" data-rawwidth="1302" src="//pic.ikafan.com/imgp/L3Byb3h5L2h0dHBzL3BpYzMuemhpbWcuY29tLzQyYjNhODRhOTUzNzU1ZDlmOWFhZDYxNmY2MzEzNDRhX2IucG5n.jpg" class="origin_image zh-lightbox-thumb" width="1302" data-original="https://pic3.zhimg.com/42b3a84a953755d9f9aad616f631344a_r.png"&amp;amp;amp;amp;amp;amp;gt;
源代码展示
# -*- coding:utf-8 -*- # https://docs.python.org/2/library/xml.dom.html#dom-nodelist-objects import xml.dom.minidom import os.path import time from openpyxl import Workbook start = time.clock() wb=Workbook() # sheet=wb.create_sheet(0,‘爬虫抓取表‘) sheet=wb.create_sheet(‘爬虫抓取表‘,0) # 2.3.5 i = 1 def get_xmlnode(node,name): return node.getElementsByTagName(name) if node else [] def files(rootdir): file = [] for parent,dirnames,filenames in os.walk(rootdir): for filename in filenames: if filename.endswith(‘.xml‘): file.append((parent+‘/‘+filename).replace(‘\\‘,‘/‘)) return file def writedata(i,j,item): if i == 1: try: sheet.cell(row = i,column= j).value = item.tagName sheet.cell(row = i+1,column= j).value = item.firstChild.data.strip() except: sheet.cell(row = i,column= j).value = item.tagName attrtext = [] for key in item.attributes.keys(): attrvalue = item.attributes[key] attrtext.append(attrvalue.value) sheet.cell(row = i+1,column= j).value = ‘,‘.join(attrtext) else: try: sheet.cell(row = i+1,column= j).value = item.firstChild.data.strip() except: attrtext = [] for key in item.attributes.keys(): attrvalue = item.attributes[key] attrtext.append(attrvalue.value) sheet.cell(row = i+1,column= j).value = ‘,‘.join(attrtext) def curitem(nodelist,v1,v2,v3,tag=‘item‘): if nodelist: for node in nodelist: nodelist2 = node.getElementsByTagName(tag) if node else [] islast = curitem(nodelist2,v1,v2,v3) if islast==1: items = node.childNodes j=4 for item in items: global i writedata(i,j,item) j=j+1 sheet.cell(row=i+1,column=1).value = v1 sheet.cell(row=i+1,column=2).value = v2 sheet.cell(row=i+1,column=3).value = v3 i=i+1 return 2 else: return 1 def begin(): sangjin = ‘‘‘ ‘‘‘ print(sangjin) begin() print("开始处理......") path = ‘../爬虫生成表.xlsx‘ xmls = files(‘../files/‘) erpath = [] en = 0 #错误数 sheet.cell(row=1,column=1).value = ‘线索ID‘ sheet.cell(row=1,column=2).value = ‘网址路径‘ sheet.cell(row=1,column=3).value = ‘爬取时间‘ for filename in xmls: try: doc =xml.dom.minidom.parse(filename) root = doc.documentElement noderoot = get_xmlnode(root,‘item‘) clueid = get_xmlnode(root,‘clueid‘) v1=clueid[0].childNodes[0].data clueid1 = get_xmlnode(root,‘uri‘) v2=clueid1[0].childNodes[0].data clueid2 = get_xmlnode(root,‘createdate‘) v3=clueid2[0].childNodes[0].data curitem(noderoot,v1,v2,v3) print("处理成功:"+filename) except Exception as e: #raise en = en+1 erpath.append(filename+"\n"+str(e)) pass wb.save(path) total = len(xmls) if erpath: print("-"*50) print("提取失败的文件:") print(‘\n‘.join(erpath)) print("-"*50) print(‘总共处理XML条数:‘+str(total)) print(‘提取XML失败条数:‘+str(en)) print(‘处理成功的XML条数:‘+str(total-en)) print(‘生成记录数:‘+str(i-1)) print("-"*50) end = time.clock() print("程序总共运行时间 : %.03f 秒" %(end-start)) print("处理结束........") input() 只使用了xml和excel的库: import xml.dom.minidom from openpyxl import Workbook 代码使用递归形式解析,很短很短,看看就知道了: doc =xml.dom.minidom.parse(filename) root = doc.documentElement noderoot = get_xmlnode(root,‘item‘) clueid = get_xmlnode(root,‘clueid‘) v1=clueid[0].childNodes[0].data clueid1 = get_xmlnode(root,‘uri‘) v2=clueid1[0].childNodes[0].data clueid2 = get_xmlnode(root,‘createdate‘) v3=clueid2[0].childNodes[0].data curitem(noderoot,v1,v2,v3) print("处理成功:"+filename)
为了照顾那个懒人软件,所以解析了clueid等标记,因为它自带的,而主要的爬取数据是放在item标记里面,如果你要处理自己的xml文件,请联系我,因为你也许看不懂代码,哈哈哈哈。
------------------------------------我是分割线----------------------------------------------------------------------------
我到现在还没有解决乎主的问题。。。。。
手上有几千个url,url对应的是xml,怎么解决。i
可以直接爬取下来。将url写在文件里,按行读取url,然后写个循环使用http get方式获取下来。
给个例子吧,Python爬取数据万能函数:
# -*- coding:utf-8 -*- import urllib.request, urllib.parse, http.cookiejar import os import random import re # 代理ip函数 # 183.239.167.122:8080 # 返回[[‘179.176.37:8080‘, ‘179.146.153:8080‘, ‘179.198.37:8080‘, ‘234.45.50:3128‘, ‘255.53.81:80‘, ‘22.195.148:80‘] def daili(): geshi=re.compile(r‘(.*)@(.*)‘) file =open(‘daili.txt‘,‘rb‘) data=file.read().decode(‘utf-8‘,‘ignore‘).split(‘\n‘) location=[] #random.shuffle(data) # ip数组打乱 for i in range(0,len(data)): temp=geshi.match(data[i]).group(1).split(‘.‘) location.append(geshi.match(data[i]).group(2)) data[i]=‘.‘.join([temp[1],temp[2],temp[3]]) file.close() file =open(‘daili1.txt‘,‘w‘) file.write(‘\n‘.join(data)) file.close() return data # 万能抓取函数 def getHtml(url,daili=‘‘,postdata={}): """ 抓取网页:支持cookie 第一个参数为网址,第二个为POST的数据 """ # COOKIE文件保存路径 filename = ‘cookie.txt‘ # 声明一个MozillaCookieJar对象实例保存在文件中 cj = http.cookiejar.MozillaCookieJar(filename) # cj =http.cookiejar.LWPCookieJar(filename) # 从文件中读取cookie内容到变量 # ignore_discard的意思是即使cookies将被丢弃也将它保存下来 # ignore_expires的意思是如果在该文件中 cookies已经存在,则覆盖原文件写 # 如果存在,则读取主要COOKIE if os.path.exists(filename): cj.load(filename, ignore_discard=True, ignore_expires=True) # 建造带有COOKIE处理器的打开专家 proxy_support = urllib.request.ProxyHandler({‘http‘:‘http://‘+daili}) # 开启代理支持 if daili: print(‘代理:‘+daili+‘启动‘) opener = urllib.request.build_opener(proxy_support, urllib.request.HTTPCookieProcessor(cj), urllib.request.HTTPHandler) else: opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj)) # 打开专家加头部 opener.addheaders = [(‘User-Agent‘, ‘Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5‘), (‘Referer‘, ‘http://s.m.taobao.com‘), (‘Host‘, ‘h5.m.taobao.com‘)] # 分配专家 urllib.request.install_opener(opener) # 有数据需要POST if postdata: # 数据URL编码 postdata = urllib.parse.urlencode(postdata) # 抓取网页 html_bytes = urllib.request.urlopen(url, postdata.encode()).read() else: html_bytes = urllib.request.urlopen(url).read() # 保存COOKIE到文件中 cj.save(ignore_discard=True, ignore_expires=True) return html_bytes if __name__ == ‘__main__‘: url=‘http://www.baidu.com‘ a=getHtml(url,‘‘,{}) b=getHtml(url) print(a.decode(‘utf-8‘,‘ignore‘)) print(b.decode(‘utf-8‘,‘ignore‘)) data=daili() print(data) c=getHtml(url,data[0],{}) print(c.decode(‘utf-8‘,‘ignore‘))
上面如果要使用Post进行数据抓取,请直接写map,然后放在第三个参数。如果daili不是空的,就使用代理。着个涉及到反爬虫的机制,如果有足够多的人点赞,我就继续写。
代理文件daili.txt放在和源文件同级目录,格式如下:
1.179.176.37:[email protected]#泰国 TOT公共有限公司 1.179.146.153:[email protected]#泰国 TOT公共有限公司 1.179.198.37:[email protected]#泰国 TOT公共有限公司 1.234.45.50:[email protected]#韩国 SK电讯 1.255.53.81:[email protected]#韩国 SK电讯 5.22.195.148:[email protected]#【匿】伊朗 5.135.161.61:[email protected]#法国 5.141.9.86:[email protected]#俄罗斯 5.160.247.16:[email protected]#伊朗
处理后会保存在daili1.txt里面,可以打开看看。
这种代理IP去哪里找呢?免费代理ip_httpip代理地址_qq代理服务器
---------------------------------我又是分割线------------------------------------------------
写了这么多,貌似只讲了一小部分。大家可以看我写的另一篇文章,我没时间写太多,所以大部分都在脑里,有空会多来知乎吹水,刚刚入扎。
传送门:
Python3中级玩家:淘宝天猫商品搜索爬虫自动化工具(第一篇)
------------------------------爬虫技巧补充-----------------------------------------------
处理其他格式的xml,请仿照程序修改!!!