Trying to produce correct recursion - python

Didn't know who to ask at this time of night. But I'm trying to implement recursion for the first time with not much background knowledge. I am getting some result on the right track but the program is now in an infinite loop.
def url_open(url, count, position):
for i in range(count):
newURL = 0
html = urlopen(url, context=ctx).read()
soup = BeautifulSoup(html, "html.parser")
tags = soup.find_all("a")
newURL = dict_populate(tags, position)
url_open(newURL, count - 1, position)
def dict_populate(tags, position):
workingCOUNT = 0
workingDICT = {}
newURL = 0
for tag in tags:
workingCOUNT += 1
for key,value in tag.attrs.items():
workingDICT[workingCOUNT] = value
new = workingDICT[position]
return new
url = input("Enter - ")
var1 = input("Enter count - ")
var2 = input("Enter position - ")
searchCOUNT = int(var1)
urlPOSI = int(var2)
url_open(url, searchCOUNT, urlPOSI)
print("The last url retrieved: ", url)
It works with low values of count 1, 2, 3, but over that it gets into an infinite loop.
Any suggestions?
EDIT:
I have posted the whole program.
This program parses webpage for a URL. The website that I'm asked to use is a website that contains links to other websites of the same links but in different order. I need to find the url in position n and that repeat the process for n other websites until I find the last one.

Have a look at while statement.
While Loops is used to execute a block of statements repeatedly until a given condition is satisfied.
# assign a default value to a variable called "count"
count = 0
# iterate until test expression is False
while (count < 5):
count += 1;
# print results
print("count is :" + str(count) )
Output:
count is :1
count is :2
count is :3
count is :4
count is :5
Obviously, you can manage while statements inside a for loop.
for item in my_items_list:
while some_conditions:
# do something here

Related

Find_between function with indexed output?

I'd like to use the find_between function to retrieve index-able values from a specific web server.
I'm using the requests module to gather some source code from a specific website seen on line 18:
response = requests.get("https://www.shodan.io/search?query=Server%3A+SQ-WEBCAM")
and I'd like to call the find_between function to retrieve all the values (all items on page each item represented by the incrementing value of 'n') with the specified find_between parameters:
x = find_between(response.content,'/></a><a href="/host/','">---')
Anyone know how to pull this off?
import sys
import requests
from time import sleep
# Find between page tags on page.
def find_between( s, tag1, tag2 ):
try:
start = s.index( tag1 ) + len( tag1 )
end = s.index( tag2, start )
return s[start:end]
except ValueError:
return ""
def main():
# Default value for 'n' index value (item on page) is 0
n = 0
# Enter the command 'go' to start
cmd = raw_input("Enter Command: ")
if cmd == "go":
print "go!"
# Go to this page for page item gathering.
response = requests.get("https://www.shodan.io/search?query=Server%3A+SQ-WEBCAM")
# Initial source output...
print response.content
# Find between value of 'x' sources between two tags
x = find_between(response.content,'/></a><a href="/host/','">---')
while(True):
# Wait one second before continuing...
sleep(1)
n = n + 1
# Display find_between data in 'x'
print "\nindex: %s\n\n%s\n" % (n, x)
# Enter 'exit' to exit script
if cmd == "exit":
sys.exit()
# Recursive function call
while(True):
main()
A few things in your code appear to need addressing:
The value of x is set outside (before) your while loop, so the loop increments the index n but prints the same text over and over because x never changes.
find_between() returns only a single match, and you want all matches.
Your while loop never ends.
Suggestions:
Put the call to find_between() inside the while loop.
Each successive time you call find_between(), pass it only the portion of the text following the previous match.
Exit the while loop when find_between() finds no match.
Something like this:
text_to_search = response.content
while(True):
# Find between value of 'x' sources between two tags
x = find_between(text_to_search, '/></a><a href="/host/', '">---')
if not x:
break
# Wait one second before continuing...
sleep(1)
# Increment 'n' for index value of item on page
n = n + 1
# Display find_between data in 'x'
print "\nindex: %s\n\n%s\n" % (n, x)
# Remove text already searched
found_text_pos = text_to_search.index(x) + len(x)
text_to_search = text_to_search[found_text_pos:]

My file has no length? Even though it does

def file_contents():
global file_encrypt
encryption_file = input("What is the name of the file?")
file_encrypt = open(encryption_file, 'r')
contents = file_encrypt.read()
print (contents)
ask_sure = input("Is this the file you would like to encrypt?")
if ask_sure == "no":
the_menu()
This part of the code opens the file the user enters, right? There are no real problems here.
def key_offset():
key_word = ''
count = 0
total = 0
while count < 8:
num = random.randint (33, 126)
letter = chr(num)
key_word = key_word + letter
count = count + 1
offset = ord(letter)
total = total + offset
print("Make sure you copy the key for decryption.")
if count == 8:
total = total/8
total = math.floor(total)
total = total - 32
print(key_word)
return total
This is the part where it calculates the offset and etc etc. Once again no problems here.
def encrypting():
file = file_contents()
total = key_offset()
encrypted = ''
character_number = 0
length = len(file_encrypt)
And then this is where the problem appears, I have made the variable file_encrypt global in the first block of code, so therefore it should work. I have tried calling it under another variable like file_en = file_encrypt and used file_en in the length calculating, but it keeps saying it has no length... I have tried asking friends and my teacher, but they seem clueless. The problem is that every time i get to this part it says that file_encrypt has no length or the other way I tried it, file_en has no length, something to do with TextWrapper.io.
file_encrypt is a file pointer, which does indeed not have a length. The contents of your file are in contents, but that is a variable local to the file_contents function.
Really you should not be using global variables; there isn't any reason to here. Instead, return the actual data - contents - from file_contents, then you can use it in the calling function.
There are a few issues with your code, but ignoring those for now, I think your main problems are:
1) The function "file_contents" doesn't return anything, I suspect you want to return "contents". Hard to say without knowing what you want to do with the "file" variable.
def encrypting():
file = file_contents() # <--
2) As others have said, "file_encrypt" is a pointer to a file, although in this function you didn't declare it as global, so it's probably None.
def encrypting():
file = file_contents()
total = key_offset()
encrypted = ''
character_number = 0
length = len(file_encrypt) # <--
So, these modifications should give you what you need:
def file_contents():
global file_encrypt
encryption_file = input("What is the name of the file?")
file_encrypt = open(encryption_file, 'r')
contents = file_encrypt.read()
print (contents)
ask_sure = input("Is this the file you would like to encrypt?")
if ask_sure == "no":
the_menu()
return contents # <-- ADDED
def encrypting():
contents = file_contents() # <-- MODIFIED
total = key_offset()
encrypted = ''
character_number = 0
length = len(contents) # <-- MODIFIED

How do I store information collected from a for loop and assign it to a variable with the count iteration?

I am creating a program that will take input, and output opening and closing html tags around the input in a list. Obviously the code below will just print the last input that was entered on the last run count times. I would guess that a new variable must be created based on the count during each pass. How do I accomplish this?
runNum = int( input( "How many items are you entering? : "))
print ("Type 1 if you would like to use the li tag or type 2 for the th tag")
descVar = input("")
if descVar == "1":
for count in range ( 1, runNum + 1):
print ("Please enter item #", count, "")
item = input()
for count in range (1, runNum):
print ( <li>, item, </li> )
just collect the input in a list:
items = []
for count in range ( 1, runNum + 1):
print ("Please enter item #", count, "")
item = input()
items.append(item)
for item in items:
print ("<li>",item,"</li>")

python loop in array adding individual item prices

I have the following code mostly working. I just need it to allow the user to input "add-ins" until they enter the sentinel value to exit the loop and have it add the selections up. This is for a class assignment, but this is all I am having difficulties with. Any help would be appreciated.
#start
def main(): #create a module - python function to hold main processing
#declarations
addinArray = ["Whipped Cream", "Cinnamon", "Chocolate sauce", "Amaretto", "Irish whiskey"]
priceArray = [0.89, 0.25, 0.59, 1.50, 1.75] #this array holds the add-in prices
loopFlag = "" #sentinal value for looping
cnt = 0
COFFEECOST = 2 #constant to coffee cost
addinName = ""
totalCost = 0
#input enter add-in name
addinName = input("Enter on Keyboard Coffee Add-in (ex. Whipped Cream, Cinnamon, etc.) or Done to quit")
while (addinName != "Done"): #loop until addinName is Done
while (cnt < len(addinArray)):
if (addinName == addinArray[cnt]) :
totalCost = priceArray[cnt] + totalCost
print("Add-in ", addinName, " with a price of ", priceArray[cnt])
print( "with a total add-in price so far of ", totalCost)
cnt = cnt + 1 #increment counter for next element in array
#end while
addinName = input("Enter on Keyboard Coffee Add-in (ex. Whipped Cream, Cinnamon, etc.) or Done to quit")
#end while
totalCost = totalCost + COFFEECOST
print("Total cost is: ", totalCost)
main()
#stop
I think that cnt = 0 should reset after the first loop:
while (addinName != "Done"): #loop until addinName is Done
cnt = 0
Without this, after the first add-on cnt can reach len(addinArray) and never second while loop is going to be executed for new add-on.
I ran your code locally and I found 2 things.
You need to reset the cnt variable to zero after the nested while loop, otherwise it won't get executed again since the condition cnd>5 will be always true.
The input() call seems to throw an error, so instead I tested raw_input() and seemed to work.
Hope this helps!

Python return function not working for me

I have the following code:
#gets the filename from the user
b= input("Please enter a file name to be opened: ")
a = (b+".txt")
#main data storage and other boolean options
data =[]
result1 =[]
on = True
#File reading in main body with try and except functionality.
try:
check = open(a, 'r')
line =check.readlines()
for items in line:
breakup= items.split()
number, salary, position, first, oname1, oname2, last = breakup
data.append(tuple([last, first + ' ' + oname1 + ' ' + oname2, number, position, salary]))
except IOError as e :
print("Failed to open", fileName)
#Employee creation function, takes the line and stores it in the correct position.
def employee_creation():
result = [((item[0] +", "+ item[1]).ljust(30), int(item[2]), item[3].ljust(15), int(item[4])) for item in data]
for items in result:
result1.append((items[0][0:30], format(items[1], "^5d"), items[2][0:15], "£"+format((items[3]),"<8d")))
return(result)
employee_creation()
print(result)
while on == True:
print("Please select what option you would like to use to search for employees:")
option = int(input("""
1 - Salary (X to X)
2 - Job Titlle
3 - Name, Payroll Number
:"""))
if option == 1:
start = input("What range would you like to start from: ")
end = input("What is the maximum range you would like :")
for items in result:
print(items[3])
if items[3]>start and items[3]<end:
print(items)
else:
print("No employees with this information can be found")
on= False
else:
on= False
However my def employee_creation() doesn't actually return result. I need it to make it a global variable so that I can use it to launch personal querys against the data.
Can anyone see why its not working?
No need to use the evil global variables. You forgot to store the result of your function to another variable.
def employee_creation():
result = [((item[0] +", "+ item[1]).ljust(30), int(item[2]), item[3].ljust(15), int(item[4])) for item in data]
for items in result:
result1.append((items[0][0:30], format(items[1], "^5d"), items[2][0:15], "£"+format((items[3]),"<8d")))
return result # no need for () here
result = employee_creation() # store the return value of your function
print(result)

Categories