【发布时间】:2015-10-20 03:59:09
【问题描述】:
我正在使用 Python 和 Beautifulsoup 解析美国专利 XML 文件(从 Google patent dumps 下载);解析后的数据导出到MYSQL数据库。
每年的数据包含接近 200-300K 的专利 - 这意味着解析 200-300K xml 文件。
我运行 python 脚本的服务器非常强大 - 16 个内核、160 GB 的 RAM 等,但解析一年的数据仍然需要将近 3 天的时间。
自 2 年以来我一直在学习和使用 python - 所以我可以完成一些事情,但不知道如何以最有效的方式完成它。我正在阅读它。
如何优化以下脚本以使其高效?
任何指导将不胜感激。
下面是代码:
from bs4 import BeautifulSoup
import pandas as pd
from pandas.core.frame import DataFrame
import MySQLdb as db
import os
cnxn = db.connect('xx.xx.xx.xx','xxxxx','xxxxx','xxxx',charset='utf8',use_unicode=True)
def separated_xml(infile):
file = open(infile, "r")
buffer = [file.readline()]
for line in file:
if line.startswith("<?xml "):
yield "".join(buffer)
buffer = []
buffer.append(line)
yield "".join(buffer)
file.close()
def get_data(soup):
df = pd.DataFrame(columns = ['doc_id','patcit_num','patcit_document_id_country', 'patcit_document_id_doc_number','patcit_document_id_kind','patcit_document_id_name','patcit_document_id_date','category'])
if soup.findAll('us-citation'):
cit = soup.findAll('us-citation')
else:
cit = soup.findAll('citation')
doc_id = soup.findAll('publication-reference')[0].find('doc-number').text
for x in cit:
try:
patcit_num = x.find('patcit')['num']
except:
patcit_num = None
try:
patcit_document_id_country = x.find('country').text
except:
patcit_document_id_country = None
try:
patcit_document_id_doc_number = x.find('doc-number').text
except:
patcit_document_id_doc_number = None
try:
patcit_document_id_kind = x.find('kind').text
except:
patcit_document_id_kind = None
try:
patcit_document_id_name = x.find('name').text
except:
patcit_document_id_name = None
try:
patcit_document_id_date = x.find('date').text
except:
patcit_document_id_date = None
try:
category = x.find('category').text
except:
category = None
print doc_id
val = {'doc_id':doc_id,'patcit_num':patcit_num, 'patcit_document_id_country':patcit_document_id_country,'patcit_document_id_doc_number':patcit_document_id_doc_number, 'patcit_document_id_kind':patcit_document_id_kind,'patcit_document_id_name':patcit_document_id_name,'patcit_document_id_date':patcit_document_id_date,'category':category}
df = df.append(val, ignore_index=True)
df.to_sql(name = 'table_name', con = cnxn, flavor='mysql', if_exists='append')
print '1 doc exported'
i=0
l = os.listdir('/path/')
for item in l:
f = '/path/'+item
print 'Currently parsing - ',item
for xml_string in separated_xml(f):
soup = BeautifulSoup(xml_string,'xml')
if soup.find('us-patent-grant'):
print item, i, xml_string[177:204]
get_data(soup)
else:
print item, i, xml_string[177:204],'***********************************soup not found********************************************'
i+=1
print 'DONE!!!'
【问题讨论】:
-
使用分析器在小型数据集上运行它,以查看您的问题所在。 docs.python.org/2/library/profile.html 另外,删除所有 try/except 子句并正确检查。捕捉错误是昂贵的。那东西多久打印一次控制台?每个文件一次? Ún缓冲打印也很昂贵,如果可能的话,打印更少。您还可以并行化程序以在更多线程上运行。这只会在一个核心、一个线程上运行。
-
是的,我正在研究如何让它使用所有的 CPU。我正在使用 nohup 运行脚本,以便将输出写入“nohup.out”文件。另外,我需要检查该特定值是否存在,因为有数百万条记录,如果该值不存在,脚本可能会崩溃;除非有更好的检查方法
-
也许切换到
lxml.html?有人体验到BeautifulSoup比lxml.html慢很多,f.e : blog.dispatched.ch/2010/08/16/beautifulsoup-vs-lxml-performance
标签: python mysql xml optimization beautifulsoup