Python替换“</html>”时替换抛出错误

Python Replace throwing errors when replacing "</html>"

我是 Python 的新手,我正在尝试在 Python 3.5.2 的 Anaconda 运行ning 中理解和使用来自 this link 的脚本。我不得不更改一些东西,以便脚本可以 运行 在这个版本的 Python 中,因为它是从 2013 年开始的。脚本(由没有经验的我修改)如下,我的问题是try 块在行 html = f.read().replace("</html>", "") + "</html>".

我根本无法理解右括号后面的+ "</html>"的原因。根据我在 replace() 方法上的发现,它至少需要两个参数,旧的 character/s 和新的。事实上,这个脚本跳转到 except Exception as e: 并打印出 a bytes-like object is required, not 'str'.

据我所知,这是因为读取是以字节形式完成的,而替换方法以字符串形式进行。我试着把这条线分成:

html = f.read
html = str.replace("</html>", "") + "</html>"

但这会抛出 replace() takes at least 2 arguments (1 given)。我还尝试将 html 的内容从 bytes 更改为 str 如下

html = str(f.read(), 'utf-8')
html = str.replace("</html>", "")

但这也是 returns replace() takes two arguments (1 given) 的错误。当我完全删除 html = str.replace("</html>", "") + "</html>" 并因此跳到 soup = BeautifulSoup(html) 时,我得到了一个警告,没有明确指定解析器,后来又出现了 NoneType object has no attribute get_dictionary 的 AttributeError。

如能提供有关上述行的必要性、使用原因和使用方法的任何帮助,我们将不胜感激。谢谢。

#!/usr/bin/python

import sys
import urllib.request
import re
import json

from bs4 import BeautifulSoup

import socket

socket.setdefaulttimeout(10)

cache = {}

for line in open(sys.argv[1]):
fields = line.rstrip('\n').split('\t')
sid = fields[0]
uid = fields[1]

# url = 'http://twitter.com/%s/status/%s' % (uid, sid)
# print url
tweet = None
text = "Not Available"
if sid in cache:
    text = cache[sid]
else:
    try:
        f = urllib.request.urlopen("http://twitter.com/%s/status/%s" % (uid, sid))
        print('URL: ', f.geturl())
        # Thanks to Arturo!
        # html = f.read()
        html = f.read().replace("</html>", "") + "</html>"
        soup = BeautifulSoup(html)
        jstt = soup.find_all("p", "js-tweet-text")
        tweets = list(set([x.get_text() for x in jstt]))
        # print len(tweets)
        # print tweets
        if (len(tweets)) > 1:
            continue

        text = tweets[0]
        cache[sid] = tweets[0]

        for j in soup.find_all("input", "json-data", id="init-data"):
            js = json.loads(j['value'])
            if js.has_key("embedData"):
                tweet = js["embedData"]["status"]
                text = js["embedData"]["status"]["text"]
                cache[sid] = text
                break
    except Exception as e:
        print(e)
        # except Exception as e:
        continue

    if tweet is not None and tweet["id_str"] != sid:
        text = "Not Available"
        cache[sid] = "Not Available"
    text = text.replace('\n', ' ', )
    text = re.sub(r'\s+', ' ', text)
    # print json.dumps(tweet, indent=2)
    print("\t".join(fields + [text]).encode('utf-8'))

str.replace 在其静态形式中使用 replace(从类型 class str 而不是 str 对象调用方法)。

str.replace 实际上需要 3 个参数:要作用的字符串、要替换的字符或字符串以及新的字符或字符串。

'abcd'.replace('d', 'z') 等同于 str.replace('abcd', 'd', 'z'):

print('abcd'.replace('d', 'z'))
# abcz
print(str.replace('abcd', 'd', 'z'))
# abcz

我已经接受了@DeepSpace 友善的解决方案作为答案,因为它帮助我意识到如何克服我面临的问题。下面的代码现在可以在 Python 3 if 运行 下从命令提示符执行如下(请注意,我是从 Windows 命令提示符执行的):

python download_tweets.py inpuot_file.tsv > output_file.tsv。代码如下:

#!/usr/bin/python

import sys
import urllib.request
import re
import json

from bs4 import BeautifulSoup

import socket

socket.setdefaulttimeout(10)

cache = {}

for line in open(sys.argv[1]):
    fields = line.rstrip('\n').split('\t')
    sid = fields[0]
    uid = fields[1]

    tweet = None
    text = "Not Available"
    if sid in cache:
        text = cache[sid]
    else:
        try:
           f = urllib.request.urlopen("http://twitter.com/%s/status/%s" % (uid, sid))
           # print('URL: ', f.geturl())
           # Thanks to Arturo!
           html = str.replace(str(f.read(), 'utf-8'), "</html>", "")
           # html = f.read().replace("</html>", "") + "</html>" # original line
           soup = BeautifulSoup(html, "lxml") # added "lxml" as it was giving warnings
          jstt = soup.find_all("p", "js-tweet-text")
          tweets = list(set([x.get_text() for x in jstt]))
          # print(len(tweets))
          if (len(tweets)) > 1:
            continue

          text = tweets[0]
          cache[sid] = tweets[0]

          for j in soup.find_all("input", "json-data", id="init-data"):
              js = json.loads(j['value'])
              if "embedData" in js:
                 # if js.has_key("embedData"): # original line
                 tweet = js["embedData"]["status"]
                 text = js["embedData"]["status"]["text"]
                 cache[sid] = text
                 break
        except Exception as e:
            print(e)
            continue

        if tweet is not None and tweet["id_str"] != sid:
            text = "Not Available"
            cache[sid] = "Not Available"
        text = text.replace('\n', ' ', )
        text = re.sub(r'\s+', ' ', text)
        # print(json.dumps("dump: ", tweet, indent=2))
        print(" \t ".join(fields + [text]).encode('utf-8'))