我目前正在使用此代码来计算text
文件中存在的xml
个元素的数量。
from bs4 import BeautifulSoup
soup = BeautifulSoup(open('wiki.xml'), 'lxml')
count = 0
for text in soup.find_all('text', recursive=False):
count += 1
print(count)
由于其大小,我无法显示完整的xml
文件,但这是它的快速摘要...
<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
<siteinfo>
<sitename>Wikipedia</sitename>
<dbname>simplewiki</dbname>
<base>https://simple.wikipedia.org/wiki/Main_Page</base>
<generator>MediaWiki 1.30.0-wmf.14</generator>
<case>first-letter</case>
<namespaces>
<namespace key="-2" case="first-letter">Media</namespace>
<namespace key="-1" case="first-letter">Special</namespace>
<namespace key="0" case="first-letter" />
<namespace key="1" case="first-letter">Talk</namespace>
<namespace key="2" case="first-letter">User</namespace>
<namespace key="3" case="first-letter">User talk</namespace>
<namespace key="4" case="first-letter">Wikipedia</namespace>
<namespace key="5" case="first-letter">Wikipedia talk</namespace>
<namespace key="6" case="first-letter">File</namespace>
<namespace key="7" case="first-letter">File talk</namespace>
<namespace key="8" case="first-letter">MediaWiki</namespace>
<namespace key="9" case="first-letter">MediaWiki talk</namespace>
<namespace key="10" case="first-letter">Template</namespace>
<namespace key="11" case="first-letter">Template talk</namespace>
<namespace key="12" case="first-letter">Help</namespace>
<namespace key="13" case="first-letter">Help talk</namespace>
<namespace key="14" case="first-letter">Category</namespace>
<namespace key="15" case="first-letter">Category talk</namespace>
<namespace key="828" case="first-letter">Module</namespace>
<namespace key="829" case="first-letter">Module talk</namespace>
<namespace key="2300" case="first-letter">Gadget</namespace>
<namespace key="2301" case="first-letter">Gadget talk</namespace>
<namespace key="2302" case="case-sensitive">Gadget definition</namespace>
<namespace key="2303" case="case-sensitive">Gadget definition talk</namespace>
<namespace key="2600" case="first-letter">Topic</namespace>
</namespaces>
</siteinfo>
<page>
<title>April</title>
<ns>0</ns>
<id>1</id>
<revision>
<id>5753795</id>
<parentid>5732421</parentid>
<timestamp>2017-08-11T21:06:32Z</timestamp>
<contributor>
<ip>2602:306:3433:C7F0:188F:FDE3:9FBE:D0B0</ip>
</contributor>
<model>wikitext</model>
<format>text/x-wiki</format>
<text xml:space="preserve">{{monththisyear|4}}
'''April''' is the fourth [[month]] of the [[year]], and comes between [[March]] and [[May]]. It is one of four months to have 30 [[day]]s.
April always begins on the same day of week as [[July]], and additionally, [[January]] in leap years. April always ends on the same day of the week as [[December]].
April's [[flower]]s are the [[Sweet Pea]] and [[Asteraceae|Daisy]]. Its [[birthstone]] is the [[diamond]]. The meaning of the diamond is innocence.
简而言之,对于最终产品,我希望它能够搜索page
元素以找到titles
,它将在其中搜索我输入的特定短语,然后返回该页面内的text
元素,如果找不到结果,则返回最相似的前三个。这可能吗,有人可以帮助吗?我对所使用的库很灵活,这意味着它不必为bs4
。谢谢。
编辑:
我刚刚发现,如果从上述代码中删除recursive=False
,它将返回1
而不是0
。不知道为什么吗?
编辑:
我也尝试了下面的代码,但是它也返回0
。贝娄也是我想要最终产品的例子,全部都放在字典中。
import xml.etree.ElementTree as ET
def get_data():
tree = ET.parse(open("wiki.xml"))
root = tree.getroot()
results = {}
for title in root.findall('./page/title') and text in root.findall('./page/revision/text'):
results[title] = text
return results
r = get_data()
print(len(r))
编辑:
我刚刚在xml
文件下面尝试了一些代码...
<vehicles>
<car name="BMW">
<model>850 CSI</model>
<speed>1000</speed>
</car>
<car name="Mercedes">
<model>SL65</model>
<speed>900</speed>
</car>
<car name="Jaguar">
<model>EV400</model>
<speed>850</speed>
</car>
<car name="Ferrari">
<model>Enzo</model>
<speed>2</speed>
</car>
</vehicles>
这是我使用的代码...
from bs4 import BeautifulSoup
def get_data():
soup = BeautifulSoup(open('test.xml'), 'lxml')
count = 0
for text in soup.select("vehicles car model"):
count += 1
return count
r = get_data()
print(r)
该脚本返回了正确的数字4
。但是,当我将vehicles car model
更改为page revision text
并在wiki.xml
文件上尝试时,它不起作用,仍然返回1
。注意:在wiki
文件中,文本元素更多,所以我有时间算一下自己,所以1
绝对是错误的。
编辑:
这是我一直试图用来解析文件的代码...
def parser(file_name="wiki.xml",save_to="weboffline.csv",url='http://www.mediawiki.org/xml/export-0.10/'):
doc = tree.parse(file_name)
titles = []
texts = []
for title in doc.findall('.//mediawiki{'+url+'}//page//title'):
titles.append(title)
for text in doc.findall('.//mediawiki{'+url+'}//page//revision//text'):
texts.append(text)
with open(save_to, mode='w') as file:
writer = csv.writer(file)
writer.writerow(['TITLES', 'TEXT'])
for items in zip(titles,texts):
writer.writerow(items)
但是,此CSV文件仅返回TITLES,TEXT
。有人有解决方案吗?
答案 0 :(得分:0)
recursive=False
将仅找到顶级元素的直接子级。在您显示的示例中,<mediawiki>
的唯一子项是<siteinfo>
和<page>
,没有<text>
,因此0是正确的。通过递归到结构,我们发现单个<text>
作为子元素,同时递归到<page>
然后是<revision>
。所以1是正确的!
如果要查找这样的子代子女(等),则必须使用recursive=True
(这意味着省略了recursive
选项)。
答案 1 :(得分:0)
import xml.etree.ElementTree as etree
import codecs
import csv
import time
import os
def hms_string(sec_elapsed):
h = int(sec_elapsed / (60 * 60))
m = int((sec_elapsed % (60 * 60)) / 60)
s = sec_elapsed % 60
return "{}:{:>02}:{:>05.2f}".format(h, m, s)
def strip_tag_name(t,elem):
t = elem.tag
idx = k = t.rfind("}")
if idx != -1:
t = t[idx + 1:]
return t
def parseWikiFile():
PATH_WIKI_XML = ''
FILENAME_WIKI = 'resources/wiki.xml'
FILENAME_PAGES = 'resources/weboffline.csv'
ENCODING = "utf-8"
pathWikiXML = os.path.join(PATH_WIKI_XML, FILENAME_WIKI)
pathPages = os.path.join(PATH_WIKI_XML, FILENAME_PAGES)
pageCount = 0
totalCount = 0
title = None
start_time = time.time()
with codecs.open(pathPages, "w", ENCODING) as pagesFH:
pageWriter = csv.writer(pagesFH, quoting=csv.QUOTE_MINIMAL)
pageWriter.writerow(['title', 'text'])
for event, elem in etree.iterparse(pathWikiXML, events=('start', 'end')):
tname = strip_tag_name(elem.tag,elem)
if event == 'start':
if tname == 'page':
title = ''
text = ''
else:
continue
else:
if tname == 'title':
title = elem.text
elif tname == 'text':
text = elem.text
elif tname == 'page':
totalCount += 1
pageCount += 1
pageWriter.writerow([title, text])
if totalCount > 1 and (totalCount % 100000) == 0:
print("{:,}".format(totalCount))
elem.clear()
elapsed_time = time.time() - start_time
print("Total pages: {:,}".format(totalCount))
print("Text pages: {:,}".format(pageCount))
print("Elapsed time: {}".format(hms_string(elapsed_time)))
这是我在this网站上修改的代码,效果非常好。我认为我最初试图做的只是将元素查找为位置而不是标签名称。无论如何,这行得通。