我正在编写一个python脚本来基本检查每个可能的url并在它响应请求时记录它。
我在StackOverflow上发现了一个帖子,它提出了一种为url生成字符串的方法。
for n in range(1, 4 + 1):
for comb in product(chars, repeat=n):
url = ("http://" + ''.join(comb) + ".com")
currentUrl = url
checkUrl(url)
正如你可以想象的那样,有很多网址可以使用,这需要很长时间,所以我试图找到一种方法来保存我的脚本和恢复,如果它没有了。
我的问题是如何让循环从特定的地方开始,或者是否有人有一段代码执行相同的操作并允许我在起点指定。
这是我的剧本远......
import urllib.request
from string import digits, ascii_uppercase, ascii_lowercase
from itertools import product
goodUrls = "Valid_urls.txt"
saveFile = "save.txt"
currentUrl = ''
def checkUrl(url):
print("Trying - "+url)
try:
urllib.request.urlopen(url)
except Exception as e:
None
else:
log = open(goodUrls, 'a')
log.write(url + '\n')
chars = digits + ascii_lowercase
try:
while True:
for n in range(1, 4 + 1):
for comb in product(chars, repeat=n):
url = ("http://" + ''.join(comb) + ".com")
currentUrl = url
checkUrl(url)
except KeyboardInterrupt:
print("Saving and Exiting")
open(saveFile,'w').write(currentUrl)
答案 0 :(得分:3)
尽管通过这种方法查找所有URL的尝试是荒谬的,但提出的一般问题是非常好的。简短的回答是你不能以直接的方式挑选迭代器,因为pickle机制无法保存迭代器的内部状态。但是,您可以挑选实现__iter__
和__next__
的对象。因此,如果您创建一个具有所需功能的类并且还可以作为迭代器(通过实现这两个函数),则可以对其进行pickle和重新加载。当您从中创建迭代器时,重新加载的对象将从它停止的位置继续。
#! python3.6
import pickle
class AllStrings:
CHARS = "abcdefghijklmnopqrstuvwxyz0123456789"
def __init__(self):
self.indices = [0]
def __iter__(self):
return self
def __next__(self):
s = ''.join([self.CHARS[n] for n in self.indices])
for m in range(len(self.indices)):
self.indices[m] += 1
if self.indices[m] < len(self.CHARS):
break
self.indices[m] = 0
else:
self.indices.append(0)
return s
try:
with open("bookmark.txt", "rb") as f:
all_strings = pickle.load(f)
except IOError:
all_strings = AllStrings()
try:
for s in iter(all_strings):
print(s)
except KeyboardInterrupt:
with open("bookmark.txt", "wb") as f:
pickle.dump(all_strings, f)
此解决方案还消除了对字符串长度的限制。迭代器将永远运行,最终生成所有可能的字符串。当然,在某些时候,由于宇宙的熵增加,应用程序将停止。
答案 1 :(得分:2)
itertools.product
的返回值是生成器对象。因此,你所要做的就是:
products = product(...)
for foo in products:
if bar(foo):
spam(foo)
break
# other stuff
for foo in products:
# starts where you left off.
在您的情况下,迭代可能性的时间非常短,至少与完成所有这些网络请求所需的时间相比。您可以将所有可能性保存到磁盘并转储每次运行程序后剩余的列表,或者您可以保存您正在使用的号。由于product
具有确定性输出,因此应该这样做。
try:
with open("progress.txt") as f:
first_up = int(f.read().strip())
except FileNotFoundError:
first_up = 0
try:
for i, foo in enumerate(products):
if i <= first_up:
continue # skip this iteration
# do stuff down here
except KeyboardInterrupt:
# this is really rude to do, by the by....
print("Saving and exiting"
with open("progress.txt", "w") as f:
f.write(str(i))
如果出于某种原因需要人类可读的“进度”文件,您可以像上面那样保存上一个密码并执行:
for foo in itertools.dropwhile(products, lambda p != saved_password):
# do stuff