我正在尝试创建一个脚本,该脚本从txt文件发出对随机URL的请求,例如:
import urllib2
with open('urls.txt') as urls:
for url in urls:
try:
r = urllib2.urlopen(url)
except urllib2.URLError as e:
r = e
if r.code in (200, 401):
print '[{}]: '.format(url), "Up!"
但我希望当某个网址指示404 not found
时,包含该网址的行会从文件中删除。每行有一个唯一的URL,因此基本上目标是擦除返回404 not found
的每个URL(及其对应的行)。
我怎么能做到这一点?
答案 0 :(得分:2)
您可以直接保存所有有效的网址,然后将其重写到文件中:
good_urls = []
with open('urls.txt') as urls:
for url in urls:
try:
r = urllib2.urlopen(url)
except urllib2.URLError as e:
r = e
if r.code in (200, 401):
print '[{}]: '.format(url), "Up!"
good_urls.append(url)
with open('urls.txt', 'w') as urls:
urls.write("".join(good_urls))
答案 1 :(得分:1)
最简单的方法是读取所有行,循环保存的行并尝试打开它们,然后在完成后,如果有任何URL失败,则重写该文件。
重写文件的方法是编写一个新文件,然后在成功编写和关闭新文件时,使用os.rename()
将新文件的名称更改为旧文件的名称文件,覆盖旧文件。这是安全的方法;在你知道正确写入新文件之前,你永远不会覆盖好的文件。
我认为最简单的方法就是创建一个列表来收集好的URL,并计算失败的URL数。如果计数不为零,则需要重写文本文件。或者,您可以在另一个列表中收集错误的URL。我在这个示例代码中做到了。 (我没有测试过这段代码,但我认为它应该可行。)
import os
import urllib2
input_file = "urls.txt"
debug = True
good_urls = []
bad_urls = []
bad, good = range(2)
def track(url, good_flag, code):
if good_flag == good:
good_str = "good"
elif good_flag == bad:
good_str = "bad"
else:
good_str = "ERROR! (" + repr(good) + ")"
if debug:
print("DEBUG: %s: '%s' code %s" % (good_str, url, repr(code)))
if good_flag == good:
good_urls.append(url)
else:
bad_urls.append(url)
with open(input_file) as f:
for line in f:
url = line.strip()
try:
r = urllib2.urlopen(url)
if r.code in (200, 401):
print '[{0}]: '.format(url), "Up!"
if r.code == 404:
# URL is bad if it is missing (code 404)
track(url, bad, r.code)
else:
# any code other than 404, assume URL is good
track(url, good, r.code)
except urllib2.URLError as e:
track(url, bad, "exception!")
# if any URLs were bad, rewrite the input file to remove them.
if bad_urls:
# simple way to get a filename for temp file: append ".tmp" to filename
temp_file = input_file + ".tmp"
with open(temp_file, "w") as f:
for url in good_urls:
f.write(url + '\n')
# if we reach this point, temp file is good. Remove old input file
os.remove(input_file) # only needed for Windows
os.rename(temp_file, input_file) # replace original input file with temp file
编辑:在评论中,@ abarnert建议在Windows上使用os.rename()
可能存在问题(至少我认为这就是他/她的意思)。如果os.rename()
不起作用,您应该可以使用shutil.move()
。
编辑:重写代码以处理错误。
编辑:重写以在跟踪网址时添加详细消息。这应该有助于调试。此外,我实际测试了这个版本,它适用于我。