I am new to python, I have a folder of downloaded html files, from which I need to extract the text data and output it in the same folder as text file, below code works fine with individual files, however when i am trying to pass multiple files it doesn't work. Kindly suggest a solution, i will be extremely thankful. Its not even giving me any error, so I could work on it and figure out some solution.
from HTMLParser import HTMLParser
from re import sub
from sys import stderr
from traceback import print_exc
import glob
import os
class _DeHTMLParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.__text = []
def handle_data(self, data):
text = data.strip()
if len(text) > 0:
text = sub('[ \t\r\n]+', ' ', text)
self.__text.append(text + ' ')
def handle_starttag(self, tag, attrs):
if tag == 'p':
self.__text.append('\n\n')
elif tag == 'br':
self.__text.append('\n')
def handle_startendtag(self, tag, attrs):
if tag == 'br':
self.__text.append('\n\n')
def text(self):
return ''.join(self.__text).strip()
def dehtml(text):
try:
parser = _DeHTMLParser()
parser.feed(text)
parser.close()
return parser.text()
except:
print_exc(file=stderr)
return text
def main():
dir_path = r"/home/maitreyee/Downloads/SchoolCollege.com/multiple_states/"
results_dir = r"/home/maitreyee/Downloads/SchoolCollege.com/"
for file_name in glob.glob(os.path.join(dir_path, "*.html")):
text = open(file_name, "r")
results_file = os.path.splitext(file_name)[0] + '.txt'
with open(results_file, 'w') as outfile:
i = dehtml(text)
print(i)
outfile.write(i + '\n')
if __name__ == '__main__':
main()
I struggled a lot and then tried something simpler, for the above code we could just modify the main() function by the following code and then this would return .txt files for all the html files, we need to pass just the folder location.
def main():
dir_path = r"/home/maitreyee/Downloads/SchoolCollege.com/rajasthan_data/"
results_dir = r"/home/maitreyee/Downloads/SchoolCollege.com/rajasthan_data/"
for file_name in glob.glob(os.path.join(dir_path, "*.html")):
f = open(file_name)
text = f.read()
results_file = os.path.splitext(file_name)[0] + '.txt'
with open(results_file, "w") as fp:
fp.write(dehtml(text))
fp.close()
Where the directory paths are given then put in the directory path to your html file's folder. It was really helpful for me because I had to convert hundreds of html files, and I needed all the text from them, this gave me results in seconds.
Related
I need to export my django project to static files. I'm using django-distill. Everything works fine except hrefs in main folder directory. So I decided to replace them with custom command after files were generated. However after few attempts I don't know why this function doesn't work. For example if even when I print out soup it show me empty string.
class Command(BaseCommand):
help='change urls in each header to static version'
def replace_urls(self):
find_string_1 = 'href="/blog/"'
find_string_2 = 'href="/contact/"'
replace_string_1 = 'href="blog.html"'
replace_string_2 = 'href="/contact.html"'
exclude_dirs = ['media', 'static']
for (_, dirs, files) in os.walk(f'{settings.BASE_DIR}/staticpage/'):
dirs[:] = [d for d in dirs if d not in exclude_dirs]
for filepath in files:
f = open(filepath, mode='r', encoding='utf-8')
soup = BeautifulSoup(f, "lxml", from_encoding="utf-8")
if find_string_1 in soup:
soup.replace_with(replace_string_1)
if find_string_2 in soup:
soup.replace_with(replace_string_2)
f.close()
def handle(self, *args, **kwargs):
try:
self.replace_urls()
self.stdout.write(self.style.SUCCESS(f'********** Command has been execute without any error **********'))
I am looking for a HTML converter which allows me to convert .doc to HTML in my Django project.
In my project, .docx files can be converted but not .doc files.
.docx file processing was done as follows.
view.py:
#csrf_exempt
#api_view(['POST'])
def fileload(request):
if request.method == 'POST' and request.FILES['file']:
urls = settings.MEDIA_ROOT+'fileload/'
fs = FileSystemStorage(location=urls, base_url=urls)
filename = fs.save(file.name, file)
filepath = urls + file.name
ext = os.path.splitext(filepath)[1]
print(ext)
html=None
code = '0'
if ext == '.docx':
html = get_docx_html(filepath)
code = '1'
fs.delete(file.name)
data = {
'code': code,
'html': html
}
response = JsonResponse(data)
return response
def get_docx_html(path):
with open(path, "rb") as docx_file:
result = mammoth.convert_to_html(docx_file)
html = result.value
messages = result.messages
return html
In the same way, doc files are not converted.
I'd like to have the .doc file converted.
Any idea of approach that can be recommended or sample code? Thanks a lot.
Ok, i have a python file inside my project with only this class:
class hd_XML():
def __init__(self):
self.path = 'static/XML/current/'
self.filename = 'current_settings.xml'
self.tree = ''
def open(self):
self.tree = ET.parse(self.path + self.filename)
self.root = self.tree.getroot()
return self.root
def get_data(self):
self.root = self.open()
canale = Channel
canali = []
i = 0
for child in self.root:
canale.id = child.attrib['id']
canale.max = child.attrib['max']
canale.color = child.attrib['color']
canali.append(canale)
i += 1
return canali
if i run this class standalone with:
if __name__ == '__main__':
xml = hd_XML()
print(xml.get_data())
that works. But, if I import this class in my main app file as below,
import hd_modXML #thats my separate file name
xml = hd_modXML.hd_XML()
canali = xml.get_data()
print(canali[0].id)
I cannot retrive the file...
FileNotFoundError: [Errno 2] No such file or directory: 'static/XML/current/current_settings.xml'
Why?! with a standalone file I can find it and after an import I can't?
project structure:
main folder <--- where app.py (where is included hd_modXML.py) and hd_modXML.py are
|_static
|_XML
|_current\ <-- where current_settings.xml is
|_templates
After some tries I found that it works giving the parser the whole directory path from root, so in my case:
self.path = '/home/grace/pyDev/prova_horus2/static/XML/current/'
I don't know why with prievious versions it worked without...
Now I need a way to avoid hardcoding the root path, but for this I can help myself.
Many thanks to yklsga for pointing me to the right way
I’m trying to figure out how to rename an existing text file when I change the title of the text file. If I change the title now, it’s going to create a new text file with the new title. The "old text file" that I wanted to save with a new name still exists but with the orginal name. So i got two files with the same content.
I’m creating new articles (text files) through #route('/update/', method='POST') in my ”edit templet” where title=title, text=text. Let’s say after I have created a new article with the name(title) = ”Key” and wrote a bit in that text file. Then If I want to edit/change my ”Key” article I click on that article and present the article in #route('/wiki/',)def show_article(article):. title = article, text = text)
In this template I can change my ”Key” name(title) to ”Lock”. I’m still using the same form #route('/update/', method='POST') to post my changes.
Here is the problem, it creates a new text file instead of renaming the ”Key” article to ”Lock”.
How can I change the #route('/update/', method='POST') to make it realise that I’m working with an already existing text file and only wants to rename that file.
I have tried to use two different method=’POST’ but only gets method not allowed error all the time.
from bottle import route, run, template, request, static_file
from os import listdir
import sys
host='localhost'
#route('/static/<filname>')
def serce_static(filname):
return static_file(filname, root="static")
#route("/")
def list_articles():
files = listdir("wiki")
articles = []
for i in files:
lista = i.split('.')
word = lista[0]
lista1 = word.split('/')
articles.append(lista1[0])
return template("index", articles=articles)
#route('/wiki/<article>',)
def show_article(article):
wikifile = open('wiki/' + article + '.txt', 'r')
text = wikifile.read()
wikifile.close()
return template('page', title = article, text = text)
#route('/edit/')
def edit_form():
return template('edit')
#route('/update/', method='POST')
def update_article():
title = request.forms.title
text = request.forms.text
tx = open('wiki/' + title + '.txt', 'w')
tx.write(text)
tx.close()
return template('thanks', title=title, text=text)
run(host='localhost', port=8080, debug=True, reloader=True)
You can use os.replace('old_name', 'new_name'):
import os
...
tx = open('wiki/' + title + '.txt', 'w')
tx.write(text)
os.replace(tx.name, 'name_you_want.txt') # use os.replace()
tx.close()
I am working on converting a python 2 project to python 3.4. One part of project uses LaTex and subprocess to generate PDF files. I am having issue getting the code working pass through subprocess.Popen.communicate() step. The problem is in gen_pdf() and I think it is cmd.communicate(input=self._gen_latex()) that is causing issue. If I take out try and run the code directly, it will generate error "memoryview: str object does not have the buffer interface". But I couldn't get a solution to get around of this issue.
Any help is highly appreciated. Thanks!
import django.conf
import subprocess
import os
import tempfile
import shutil
class PDFLatexWriter(object):
"""
Handles creating Latex documents and building them into PDFs.
"""
def gen_pdf(self):
"""
Generates the Latex document and writes to tmpfile.
Returns the pdf file handle.
"""
try:
args=['/usr/bin/pdflatex', '-jobname', 'dp', '-output-directory', self.tmpd, '-halt-on-error']
cmd = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stderr, stdout = cmd.communicate(input=self._gen_latex())
if cmd.poll() != 0:
print('Error running cmd.')
raise IOError
else:
return self._cp_pdf_tmp()
except Exception:
pass
finally:
self._clean_tmp()
def __init__(self, get_pdf_form, parent_dir=os.path.join(django.conf.settings.BASE_DIR+'/media', 'pdfs', 'tmp')):
"""
get_pdf_form: A validated pdfs.forms.GetPDFForm.
parent_dir: Directory where the temporary directory will be created.
"""
self.form = get_pdf_form
self.parent = parent_dir
self.tmpd = tempfile.mkdtemp(dir=self.parent)
def __del__(self):
self._clean_tmp()
def _gen_latex(self):
"""
Generates the latex markup and returns a string of the markup.
"""
header = r"""
\documentclass[a4paper,16pt]{article}
\usepackage{graphicx}
\usepackage{pdfpages}
\usepackage{hyperref}
\usepackage{fancyhdr}
\begin{document}
\pagestyle{fancy}
\fancyhead[C]{\includegraphics[width=9mm]{%s}\huge{ Student Book}}
""" % os.path.join(django.conf.settings.BASE_DIR, 'static', 'images', 'logo.png')
footer = '\n\n\end{document}'
links = ''
docs = ''
hyperlink = 2
for x, i in enumerate(self.form.iter_pdf()):
docs += r"\includepdf[pages=%s,link,linkname=%s]{%s}" % (i[1], i[0].pdf_display_name, i[0].pdf_path)
docs += '\n'
if i[1] == '-':
# Complete PDF.
links += r"\noindent\hyperlink{page.%s}{%s}\newline" % (hyperlink,
i[0].pdf_display_name)
hyperlink += i[0].pages
else:
links += r"\noindent\hyperlink{page.%s}{%s (Page %s)}\newline" % (hyperlink,
i[0].pdf_display_name, i[1])
hyperlink += 1
links += '\n'
return header + '\n\n' + links + '\n\n' + docs + '\n\n' + footer
def _cp_pdf_tmp(self):
"""
gen_pdf() creates a temp directory that includes latex build files and the PDF. Unfortunately,
a temp directory will not automatically delete when the last reference is closed. Therefore,
it's necessary to manually delete this temp dir before returning from the view. However,
we can't send the PDF to the user if we've already deleted its containing dir. This function
copies the PDF to a true temp file that will delete on close, allowing us to have the desired
behavior where the temp dir is manually deleted, and the PDF is deleted upon close.
Returns a file handle to the PDF.
"""
if os.path.isfile(os.path.join(self.tmpd, 'dp.pdf')):
tmp = tempfile.TemporaryFile(dir=self.parent, mode='r+b')
shutil.copyfileobj(open(os.path.join(self.tmpd, 'dp.pdf'), 'rb'), tmp)
tmp.seek(0)
return tmp
else:
print('No source file.')
raise IOError
def _clean_tmp(self):
"""
Cleans up temp directory.
"""
try:
shutil.rmtree(self.tmpd)
except OSError:
print('Unable to clean temporary files.')
Added Traceback
Traceback:
File "/usr/lib/python3/dist-packages/django/core/handlers/base.py" in get_response
112. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3/dist-packages/django/contrib/auth/decorators.py" in _wrapped_view
22. return view_func(request, *args, **kwargs)
File "/var/django/project1/project1/pdfs/views.py" in pdf_share
132. pdf_fb = tex.gen_pdf()
File "/var/django/project1/project1/pdfs/latex.py" in gen_pdf
125. stdout = cmd.communicate(input=self._gen_latex())[0]
File "/usr/lib/python3.4/subprocess.py" in communicate
960. stdout, stderr = self._communicate(input, endtime, timeout)
File "/usr/lib/python3.4/subprocess.py" in _communicate
1602. input_view = memoryview(self._input)
Exception Type: TypeError at /app1/share/pdf/
Exception Value: memoryview: str object does not have the buffer interface
After fixing " stdout = cmd.communicate(input=(self._gen_latex()).encode('utf-8'))[0] ", I was able to print out all the LaTex executing details. The reason I got Popen.poll() = 1 instead of 0 was because the subprocess has been terminated with an error. After print out stdout and dig into the error, there was a logo file that had wrong path. After correcting that error, everything is working perfectly.
Hope this helps for whoever happens to work on the similar stuff like me.