【问题标题】:Python - "I/O operation on closed file" when there is no filePython - 没有文件时的“关闭文件上的 I/O 操作”
【发布时间】:2014-06-02 18:24:00
【问题描述】:

我正在使用 Selenium 在 Python 中编写一个网络爬虫,该爬虫进入一个页面,获取页面的源代码,按下 JavaScript 按钮转到下一页,然后重复。当我运行我的代码时,它会启动 Firefox 并浏览所有页面,但是当它完成并尝试对页面内容执行任何操作时,它会返回:

Traceback (most recent call last):
  File "C:\Users\...\crawler.py", line 24, in test_pull
    print(contents)
ValueError: I/O operation on closed file.

我要执行的代码是:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
import sys,io
from Parser import HTMLParser

class TestPull(unittest.TestCase):
   def setUp(self):
       self.driver = webdriver.Firefox()
       self.driver.implicitly_wait(30)
       self.base_url = "some_url"
       self.verificationErrors = []
       self.accept_next_alert = True

   def test_pull(self):
       driver = self.driver
       driver.get(self.base_url)
       contents = "" 
       num = 1
       valid = 1
       while valid == 1:
          num += 1
          contents += driver.page_source

          if self.is_element_present(By.ID, "contentright_3_next_page") == True:
              driver.find_element_by_id("contentright_3_next_page").click()
          else: 
              valid = 0

       parser = HTMLParser()
       parser.feed(contents)

    def is_element_present(self, how, what):
        try: self.driver.find_element(by=how, value=what)
        except: return False
        return True

    def is_alert_present(self):
        try: self.driver.switch_to_alert()
        except: return False
        return True

    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to_alert()
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True

    def tearDown(self):
        self.driver.quit()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()

如果我删除打印语句,输出仍然是:

Traceback (most recent call last):
  File "C:\Users\...\crawler.py", line 36, in test_pull
    parser.feed(contents)
  File "C:\Python34\lib\html\parser.py", line 165, in feed
    self.goahead(0)
  File "C:\Python34\lib\html\parser.py", line 222, in goahead
    k = self.parse_starttag(i)
  File "C:\Python34\lib\html\parser.py", line 413, in parse_starttag
    self.handle_starttag(tag, attrs)
  File "C:\Users\...\crawler.py", line 20, in handle_starttag
    print(attrs[1][1])
ValueError: I/O operation on closed file.

我的解析器是:

from urllib.request import urlopen
from html.parser import HTMLParser
import sys,io

text_file = open("output.txt", "w")

class HTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            if attrs[0][0] == 'title':
                print(attrs[1][1])
                text_file.write(str(attrs[1][1]) + '\n')
    def handle_endtag(self, tag):
        ''' if tag == 'a':
        print(HTMLParser.getpos(self))
        print("Encountered a end tag:", tag)'''
    def handle_data(self, data):
        '''print("Encountered some data  :", data)'''

    text_file.close()

我已经搜索了此错误的解决方案,我能找到的每个问题都与打开、关闭的文件有关(在 for/while 循环中),然后他们尝试访问/写入文件。我已经对我的代码进行了更改,因此它正在写入单个字符串(而不是写入文本文件),然后通过我的解析器运行这批源代码,它仍然给我这个错误。

我不认为应该有一个文件要关闭,我不认为内容字符串应该导致这种冲突(尽管我对 python 还很陌生,还不知道语言的所有细微差别)。有人可以解释发生了什么以及我该如何纠正吗?

【问题讨论】:

  • 请提供更多上下文(代码)。您是否有可能在某个地方重新定义 sys.stdout?
  • 更新了更多代码。是的,我这样做了,这是为了解决一些编解码器和 unicode 问题。
  • 你能告诉我们crawler.py吗?这绝对是您的 sys.stdout 重定向的问题,但最好看看实际异常点周围发生了什么。
  • 添加了 parser.py 并添加了 TestPull 的其余部分。我不知道它是否会有所帮助,但它在得到解析器的调用之前就崩溃了。
  • 替换sys.stdout 是粗略的。我建议不要覆盖它,并在继续之前处理 UTF8 问题。

标签: python selenium web-scraping web-crawler


【解决方案1】:
#!/usr/bin/env python

from urllib.request import urlopen
from html.parser import HTMLParser
import sys,io

class HTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            if attrs[0][0] == 'title':
                print(attrs[1][1])
                with open('output.txt', 'w') as text_file:
                    text_file.write(str(attrs[1][1]) + '\n')
    def handle_endtag(self, tag):
        ''' if tag == 'a':
        print(HTMLParser.getpos(self))
        print("Encountered a end tag:", tag)'''
    def handle_data(self, data):
        '''print("Encountered some data  :", data)'''

    text_file.close()

【讨论】:

    猜你喜欢
    • 2016-03-06
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2015-07-20
    • 2015-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多