【发布时间】:2014-05-03 07:57:00
【问题描述】:
我正在尝试在下面的代码中运行带有计数器的循环。
import sys
import imaplib
import getpass
import email
import email.header
import datetime
from bs4 import BeautifulSoup
import re
from lxml import etree, html
from HTMLParser import HTMLParser
EMAIL_ACCOUNT = "sample@gmail.com"
EMAIL_FOLDER = "INBOX"
def stringify_children(node):
from lxml.etree import tostring
from itertools import chain
parts = ([node.text] +
list(chain(*([c.text, tostring(c), c.tail] for c in node.getchildren()))) +
[node.tail])
# filter removes possible Nones in texts and tails
return ''.join(filter(None, parts))
def process_mailbox(M):
"""
Do something with emails messages in the folder.
For the sake of this example, print some headers.
"""
rv, data = M.search(None, "ALL")
if rv != 'OK':
print "No messages found!"
return
for num in data[0].split():
rv, data = M.fetch(num, '(RFC822)')
if rv != 'OK':
print "ERROR getting message", num
return
msg = email.message_from_string(data[0][1])
if msg.is_multipart():
html = None
print "Checking for html or text"
for part in msg.get_payload():
if part.get_content_charset() is None:
charset = chardet.detect(srt(part))['encoding']
else:
charset = part.get_content_charset()
if part.get_content_type() == 'text/plain':
text = unicode(part.get_payload(decode=True),str(charset),"ignore").encode('utf8','replace')
f = open('email.txt', 'w')
f.write(text)
f.close
if part.get_content_type() == 'text/html':
html = unicode(part.get_payload(decode=True),str(charset),"ignore").encode('utf8','replace')
f = open('email.html','w')
f.write(html)
f.close
if part.get('Content-Disposition') is None:
continue
filename = part.get_filename()
if not os.path.isfile(filename) :
fp = open(filename, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
return 0
if html is None:
return text.strip()
else:
return html.strip()
class MLStripper(HTMLParser):
def __init__(self):
self.reset()
self.fed = []
def handle_data(self, d):
self.fed.append(d)
def get_data(self):
return ''.join(self.fed)
def strip_tags(html):
s = MLStripper()
s.feed(html)
return s.get_data()
def parse_html():
htmldoc = open('email.html', 'r+')
doc = htmldoc.read()
doc = re.sub('foobar', 'bar', doc)
soup = BeautifulSoup(open("email.html"))
VALID_TAGS = ['iframe', 'video', 'o>', 'li', 'sub', 'sup', 'source', 'br', 'h3', 'h4', 'h6', 'hr', 'q', 'mark','wbr', 'audio','strong', 'em', 'p','ul', 'li', 'br', 'blockquote', 'pre', 'del', 'h3', 'body', 'header', 'html', 'title', 'div', 'img', 'a']
for tag in soup.findAll(True):
if tag.name == 'i':
tag.name = 'em'
elif tag.name == 'cite':
tag.name = 'em'
elif tag.name == 'b':
tag.name = 'strong'
elif tag.name == 'kdb':
tag.name = 'strong'
elif tag.name == 'var':
tag.name = 'strong'
elif tag.name == 'aside':
tag.name = 'blackquote'
elif tag.name == 'code':
tag.name = 'pre'
elif tag.name == 'samp':
tag.name = 'pre'
elif tag.name == 's':
tag.name = 'del'
elif tag.name == 'h1':
tag.name = 'h3'
elif tag.name == 'h2':
tag.name = 'h3'
pretty_soup = soup.prettify()
docstring = str(pretty_soup)
tree = etree.fromstring(docstring)
walkAll = tree.iterchildren()
count = 0
for elt in walkAll:
if count <= 300:
child = stringify_children(elt)
childtext = strip_tags(child)
childstring = childtext.replace(" ", "")
for i in childstring:
count = count + len(i)
print count
else:
root = etree.Element("elt")
root.text = ''
root.tail = ''
etroot = tree.getroottree()
results = etree.tostring(etroot)
htmldoc.write(results)
M = imaplib.IMAP4_SSL('imap.gmail.com')
try:
rv, data = M.login(EMAIL_ACCOUNT, getpass.getpass())
except imaplib.IMAP4.error:
print "LOGIN FAILED!!! "
sys.exit(1)
print rv, data
rv, mailboxes = M.list()
if rv == 'OK':
print "Mailboxes:"
print mailboxes
rv, data = M.select(EMAIL_FOLDER)
if rv == 'OK':
print "Processing mailbox...\n"
process_mailbox(M)
M.close()
parse_html()
else:
print "ERROR: Unable to open mailbox ", rv
M.logout()
但是我下面的循环坏了,我不明白为什么。当计数达到 300 时,应该执行 else 语句中的代码,但计数器会继续遍历元素。
我希望在计数达到 300 之后对每个元素执行 else 语句。结果会影响达到 300 之后的元素,并且在计数达到 300 之前迭代的元素不会受到影响。我在 else 语句中放了一个打印“测试”来测试它,它没有被打印出来。
此代码的目的是抓取一封电子邮件并计算电子邮件中的文本,当总文本计数达到某个参数时,在本例中为 300,否则执行并清除剩余元素中的文本。我随机用了300。文本限制也可以是 50。
count = 0
for elt in walkAll:
if count <= 300:
child = stringify_children(elt)
childtext = strip_tags(child)
childstring = childtext.replace(" ", "")
for i in childstring:
count = count + len(i)
print count
else:
root = etree.Element("elt")
root.text = ''
root.tail = ''
编辑
我可以在 count = count + len(i) 之后插入一个 if break 条件,这将停止循环,如下所示:
count = 0
for elt in walkAll:
if count <= 300:
child = stringify_children(elt)
childtext = strip_tags(child)
childstring = childtext.replace(" ", "")
for i in childstring:
count = count + len(i)
if count >= 300:
break
print count
else:
root = etree.Element("elt")
root.text = ''
root.tail = ''
这打破了计数,但 else 语句仍然没有运行
【问题讨论】:
-
因为它位于 Stack Overflow 上,所以您的缩进不正确。
if count <= 300:行之后应该有一个缩进。 -
一旦
count在上一次迭代中达到300,else语句将对walkAll中的每个元素执行一次 - 这不是您想要的吗? -
仅供参考,我必须添加 pretty_soup = soup.prettify().encode('utf8') 才能让您的代码为我工作。
-
我希望在计数达到300之后对每个元素执行else语句。结果会影响达到300之后的元素,并且在计数达到300之前迭代的元素不会受到影响。我在 else 语句中放了一个打印“测试”来测试它,它没有被打印出来。
-
@DanielKane 运行代码时 count 会得到什么值?
标签: python if-statement for-loop counter