Cara menghapus JavaScript & tag lain menggunakan Python… tanpa mengimpor modul
Untuk bagian pertama dari proyek sekolah, saya mencoba mencari cara untuk menghapus JavaScript <script {...} >dan </script {...} >tag serta apa pun di antara <dan >.
Namun kami tidak dapat mengimpor modul apa pun (bahkan yang dibangun dengan Python) karena tampaknya penanda mungkin tidak dapat mengaksesnya, dll.
Saya mencoba ini:
text = "<script beep beep> hello </script boop doop woop> hello <hi> hey <bye>"
while text.find("<script") >= 0:
script_start = text.find("<script")
script_end = text.find(">", text.find("</script")) + 1
text = text[:script_start] + text[script_end:]
while text.find("<") >= 0:
script2_start = text.find("<")
script2_end = text.find(">") + 1
text = text[:script2_start] + text[script2_end:]
Dan itu berfungsi untuk file yang lebih kecil tetapi proyek berkaitan dengan file teks besar (pengujian sederhana yang kami berikan adalah 10,4MB) sehingga tidak selesai & hanya macet.
Ada yang punya ide untuk membuatnya lebih efisien?
Jawaban
Anda tidak perlu menghapus apapun. Faktanya: Anda tidak ingin mengubah string.
String tidak dapat diubah: setiap kali Anda "mengubah" satu, Anda malah membuat yang baru dan membuang yang lama. Itu hanya pemborosan prosesor dan memori.
Anda mengoperasikan file - jadi proseslah sesuai karakter:
- ingat apakah Anda di dalam
<...>atau tidak - jika demikian, hanya karakter penting yang
>keluar lagi - jika di luar dan karakter
<Anda masuk ke dalam dan abaikan karakter itu - jika di luar dan bukan
<Anda menulis karakter ke output (-file)
# create file
with open("somefile.txt","w") as f:
# up the multiplicator to 10000000 to create something in the megabyte range
f.write("<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata\n"*10)
# open file to read from and file to write to
with open("somefile.txt") as f, open("otherfile.txt","w") as out:
# starting outside
inside = False
# we iterate the file line by line
for line in f:
# and each line characterwise
for c in line:
if not inside and c == "<":
inside = True
elif inside and c != ">":
continue
elif inside and c == ">":
inside = False
elif not inside:
# only case to write to out
out.write(c)
print(open("somefile.txt").read() + "\n")
print(open("otherfile.txt").read())
Keluaran:
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
Jika Anda tidak diizinkan untuk mengoperasikan file secara langsung, baca file tersebut ke dalam daftar yang menghabiskan memori 11 + Mbyte:
data = list("<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata\n" * 10)
result = []
inside = False
for c in data:
if inside:
if c == ">":
inside = False
# else ignore c - because we are inside
elif c == "<":
inside = True
else:
result.append(c)
print(''.join(result))
ini masih lebih baik daripada mencari kemunculan pertama "<" dalam daftar secara berulang, tetapi mungkin memerlukan hingga dua kali memori sumber Anda (jika tidak mengandung <..> Anda menggandakan daftar).
Mengoperasikan file jauh lebih hemat memori daripada melakukan modifikasi daftar di tempat (yang akan menjadi cara ketiga untuk melakukan ini).
Ada beberapa hal mencolok yang juga perlu Anda atasi, fe
<script type="text/javascript">
var i = 10;
if (i < 5) {
// some code
}
</script>
akan meninggalkan "kode" di dalam.
Ini mungkin melakukan kasus sudut yang lebih mudah:
# open file to read from and file to write to
with open("somefile.txt") as f, open("otherfile.txt","w") as out:
# starting outside
inside = False
insideJS = False
jsStart = 0
# we iterate the file line by line
for line in f:
# string manipulation :/ - will remove <script ...> .. </script ..>
# even over multiple lines - probably missed some cornercases.
while True:
if insideJS and not "</script" in line:
line = ""
break
if "<script" in line:
insideJS = True
jsStart = line.index("<script")
jsEnd = len(line)
elif insideJS:
jsStart = 0
if not insideJS:
break
if "</script" in line:
jsEnd = line.index(">", line.index("</script", jsStart))+1
line = line[:jsStart] + line[jsEnd:]
insideJS = False
else:
line = line[:jsStart]
# and each line characterwise
for c in line:
# ... same as above ...
Meskipun ada 2 while loop, itu tetap merupakan kompleksitas linier
string = "<script beep beep> hello </script boop doop woop> hello <hi> hey <bye>"
new_string = ''
i = 0
while i < len(string):
if string[i] == "<":
while i < len(string):
i += 1
if string[i] == '>':
break
else:
new_string += string[i]
i += 1
print(new_string)
Keluaran:
hello hello hey
Berikut satu pendekatan dengan FSA :
output = ''
NORMAL, INSIDE_TAG = range(2) # availale states
state = NORMAL # start with normal state
s = '<script beep beep> hello </script boop doop woop> hello <hi id="someid" class="some class"><a> hey </a><bye>'
for char in s:
if char == '<': # if we encounter '<' we enter the INSIDE_TAG state
state = INSIDE_TAG
continue
elif char == '>': # we can safely exit the INSIDE_TAG state
state = NORMAL
continue
if state == NORMAL:
output += char # add the char to the output only if we are in normal state
print(output)
Jika penguraian semantik tag diperlukan, pastikan untuk menggunakan tumpukan (dapat diimplementasikan dengan list).
Ini akan meningkatkan kompleksitas tetapi Anda mencapai pemeriksaan yang kuat dengan FSM.
lihat contoh berikut:
output = ''
(
NORMAL,
TAG_ATTRIBUTE,
INSIDE_JAVASCRIPT,
EXITING_TAG,
BEFORE_TAG_OPENING_OR_ENDING,
TAG_NAME,
ABOUT_TO_EXIT_JS
) = range(7) # availale states
state = NORMAL # start with normal state
tag_name = ''
s = """
<script type="text/javascript">
var i = 10;
if (i < 5) {
// some code
}
</script>
<sometag>
test string
<a href="http://google.com"> another string</a>
</sometag>
"""
for char in s:
# print(char, '-', state, ':', tag_name)
if state == NORMAL:
if char == '<':
state = BEFORE_TAG_OPENING_OR_ENDING
else:
output += char
elif state == BEFORE_TAG_OPENING_OR_ENDING:
if char == '/':
state = EXITING_TAG
else:
tag_name += char
state = TAG_NAME
elif state == TAG_ATTRIBUTE:
if char == '>':
if tag_name == 'script':
state = INSIDE_JAVASCRIPT
else:
state = NORMAL
elif state == TAG_NAME:
if char == ' ':
state = TAG_ATTRIBUTE
elif char == '>':
if tag_name == 'script':
state = INSIDE_JAVASCRIPT
else:
state = NORMAL
else:
tag_name += char
elif state == INSIDE_JAVASCRIPT:
if char == '<':
state = ABOUT_TO_EXIT_JS
else:
pass
# output += char
elif state == ABOUT_TO_EXIT_JS:
if char == '/':
state = EXITING_TAG
tag_name = ''
else:
# output += '<'
state = INSIDE_JAVASCRIPT
elif state == EXITING_TAG:
if char == '>':
state = NORMAL
print(output)
KELUARAN:
test string
another string