2016-05-22 1 views
1

я работаю с этим кодом:LXML просмотр каталога парсер для HTML файлов

import lxml.etree as et 
import os 
import glob 

import contextlib 


@contextlib.contextmanager 
def stdout2file(fname): 
    import sys 
    f = open(fname, 'w') 
    sys.stdout = f 
    yield 
    sys.stdout = sys.__stdout__ 
    f.close() 


def skip_to(fle, line): 
     with open(fle) as f: 
      pos = 0 
      cur_line = f.readline().strip() 
      while not cur_line.startswith(line): 
       pos = f.tell() 
       cur_line = f.readline() 
      f.seek(pos) 
      return et.parse(f) 


def trade_spider(): 
    os.chdir(r"F:\ABC") 
    with stdout2file("Test123.txt"): 
     for file in glob.iglob('**\*.html', recursive=True): 
      xml = skip_to(file, "<?xml") 
      tree = xml.getroot() 
      nsmap = {"ix": tree.nsmap["ix"]} 
      fractions = xml.xpath("//ix:nonFraction[contains(@name, 'ABC')]", namespaces=nsmap) 
      for fraction in fractions: 
       print(file.split(os.path.sep)[-1], end="| ") 
       print(fraction.get("name"), end="| ") 
       print(fraction.text, end="|" "\n") 
       break 
trade_spider() 

и я получаю сообщение об ошибке:

C:\Users\Anaconda3\python.exe C:/Users/PycharmProjects/untitled/Versuch/lxmlparser.py 
Traceback (most recent call last): 
    File "C:/PycharmProjects/untitled/Versuch/lxmlparser.py", line 42, in <module> 
    trade_spider() 
    File "C:/6930p/PycharmProjects/untitled/Versuch/lxmlparser.py", line 33, in trade_spider 
    xml = skip_to(file, "<?xml") 
    File "C:/6930p/PycharmProjects/untitled/Versuch/lxmlparser.py", line 26, in skip_to 
    return et.parse(f) 
    File "lxml.etree.pyx", line 3427, in lxml.etree.parse (src\lxml\lxml.etree.c:79720) 
    File "parser.pxi", line 1803, in lxml.etree._parseDocument (src\lxml\lxml.etree.c:116182) 
    File "parser.pxi", line 1823, in lxml.etree._parseFilelikeDocument (src\lxml\lxml.etree.c:116474) 
    File "parser.pxi", line 1718, in lxml.etree._parseDocFromFilelike (src\lxml\lxml.etree.c:115235) 
    File "parser.pxi", line 1139, in lxml.etree._BaseParser._parseDocFromFilelike (src\lxml\lxml.etree.c:110109) 
    File "parser.pxi", line 573, in lxml.etree._ParserContext._handleParseResultDoc (src\lxml\lxml.etree.c:103323) 
    File "parser.pxi", line 679, in lxml.etree._handleParseResult (src\lxml\lxml.etree.c:104936) 
    File "lxml.etree.pyx", line 324, in lxml.etree._ExceptionContext._raise_if_stored (src\lxml\lxml.etree.c:10656) 
    File "parser.pxi", line 362, in lxml.etree._FileReaderContext.copyToBuffer (src\lxml\lxml.etree.c:100828) 
    File "C:\6930p\Anaconda3\lib\encodings\cp1252.py", line 23, in decode 
    return codecs.charmap_decode(input,self.errors,decoding_table)[0] 
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f in position 1789: character maps to <undefined> 

Для следующих, мой каталог состоит из 5 подпапок каждая из которых содержит до 12 подпапок, заполненных HTML-файлами. Код работает отлично, если я установил os.chdir(r"F:\ABC\201X\XXX") в каждую подпапку в каталоге «201X». Однако это даст мне вышеупомянутое сообщение об ошибке IF: 1. Я установил os.chdir as r"F:\ABC\2012\October (октябрь - первая вложенная папка в подпапке 2012, в которой синтаксический анализатор lxml. (Для ВСЕХ других подпапок это работает, однако, отлично !?) 2. Если Я установил os.chdir as r"F:\ABC. Поскольку я не хочу устанавливать все вложенные папки вручную, мое первоначальное намерение должно автоматически анализировать все вложенные папки в ABC. Я думал, что если я буду использовать for file in glob.iglob('**/*.html', recursive=True):, он будет просматривать все подпапки, содержащиеся в моем каталоге «ABC»?

Кто-нибудь сталкивался с такой проблемой раньше?

+2

Попробуйте '' open (fle, encoding = "utf = 8") как f' –

+1

Еще раз большое спасибо @PadraicCunningham! Он отлично работает в моей первой вложенной папке «Октябрь», а также в моей подпапке «2012» для разбора всех содержащихся подпапок. –

+1

не беспокойтесь, вы можете добавить его в качестве ответа, чтобы закрыть вопрос. –

ответ

1

, кодирующие счетов компаний по UnicodeDecodeError который отсортированные пути установки кодировки в UTF-8, проблема с кодом застрять в цикле, потому что не все файлы имеют "<?xml", некоторые из них <html ... пересмотренной функции исправит проблему, я также добавил некоторые отладки, чтобы вы могли видеть, какие файлы не содержат данных.

import logging 
import contextlib 
logger = logging.getLogger(__file__) 
logging.basicConfig(filename="debug.log") 
logger.setLevel(logging.DEBUG) 




@contextlib.contextmanager 
def stdout2file(fname): 
    import sys 
    f = open(fname, 'w', encoding="utf-8") 
    sys.stdout = f 
    yield 
    sys.stdout = sys.__stdout__ 
    f.close() 

def skip_to(fle, starts): 
     with open(fle) as f: 
      pos = 0 
      cur_line = f.readline().strip() 
      while not cur_line.startswith(starts): 
       pos = f.tell() 
       cur_line = f.readline() 
      f.seek(pos) 
      return et.parse(f) 

def trade_spider(): 
    os.chdir(r"C:\Users\Independent Auditors Report") 
    with stdout2file("auditfeesexpenses.txt"): 
     for file in glob.iglob('./*.html'): 
      xml = skip_to(file, ("<?xml","<html")) 
      tree = xml.getroot() 
      nsmap = {"ix": tree.nsmap["ix"]} 
      fractions = xml.xpath("//ix:nonFraction[contains(@name, 'AuditFeesExpenses')]", namespaces=nsmap) 
      for fraction in fractions: 
       print(file.split(os.path.sep)[-1], end="| ") 
       print(fraction.get("name"), end="| ") 
       print(fraction.text, end="|" "\n") 
       break 
      else: 
       logger.debug("Nothing found in file {}".format(file)) 

trade_spider() 
+0

Отлично! Это решение для моей проблемы! Единственное, что я изменил, было с open (fle, encoding = "utf = 8") как f: просто убедитесь, что нет никакой кодировки utf-8, но все остальное работает довольно аккуратно! –

-1

Хмм, я получил такую ​​ошибку при работе с файлом в python 2 с кириллическими символами и сделан на python 3.

Как я вижу, вы также похожи Может быть, это поможет вам Тип в верхней части файла

#!/usr/bin/python 

# -*- coding: utf-8 -*- 
1

Ок, это была проблема кодирования. При смене with open(fle) as f: на with open(fle,encoding="utf=8") as f и, следовательно, использование utf-8, работающего под управлением, работает без проблем.

+0

Кроме того, если не каждый файл имеет «

+0

Кроме того, если тег, который вы ищете, имеет дочерние теги, например , или что-нибудь еще, что вам нужно, чтобы заменить 'print (fraction.text, end =" | "" \ n ")' на 'print (fraction.xpath (". // text() ") [0], end =" | "" \ n ")', чтобы получить весь текст, включая детей. –

0

Final Код:

import lxml.etree as et 
import os 
import glob 
import logging 
import contextlib 

logger = logging.getLogger(__file__) 
logging.basicConfig(filename="debug.log") 
logger.setLevel(logging.DEBUG) 


@contextlib.contextmanager 
def stdout2file(fname): 
    import sys 
    f = open(fname, 'w', encoding="utf-8") 
    sys.stdout = f 
    yield 
    sys.stdout = sys.__stdout__ 
    f.close() 


def skip_to(fle, starts): 
     with open(fle, encoding="utf=8") as f: 
      pos = 0 
      cur_line = f.readline().strip() 
      while not cur_line.startswith(starts): 
       pos = f.tell() 
       cur_line = f.readline() 
      f.seek(pos) 
      return et.parse(f) 


def trade_spider(): 
    os.chdir(r"F:\XYZ") 
    with stdout2file("Test123.txt"): 
     for file in glob.iglob('**/*.html'):        
      xml = skip_to(file, ("<?xml", "<html")) 
      tree = xml.getroot() 
      nsmap = {"ix": tree.nsmap["ix"]} 
      fractions = xml.xpath("//ix:nonNumeric[contains(@name, 'NAMEATTRIBUTE')]", namespaces=nsmap) 
      for fraction in fractions: 
       print(file.split(os.path.sep)[-1], end="| ") 
       print(fraction.get("name"), end="| ") 
       print(fraction.xpath(".//text()")[0], end="|" "\n") 
       break 
      else: 
       logger.debug("Nothing found in file {}".format(file))    
trade_spider() 

Со многими благодаря @Padraic Cunningham!