Raspberry PI Writing CSV Python - python

As part of a project, I am trying to use a Raspberry PI to capture WiFi networks and write it to a CSV file. If the quality of the signal is over 30/70 I want to capture all WiFi SSIDs and their relevant MAC address and record it.
The issue seems to be relevant syntax but I cannot seem to figure out what is wrong.
def wifiscan():
ssid = []
scanoutput = check_output(["iwlist", "wlan0", "scan"])
curtime = time.strftime("%I:%M:%S")
ssid.append(curtime)
for line in scanoutput.split():
line=str(line)
if line.startswith("Quality"):
line=line[8:-25]
if(line>30 and line.startswith("ESSID")
line=line[7:-1]
ssid.append(line)
with open('/home/pi/Desktop/Project/Results/'+'test.csv','a') as csvfile:
csvwriter = csv.writer(csvfile,delimiter=',')
csvwriter.writerow(ssid)
print ssid
Update 1:
Update 2:

I made some changes to your code but i don't know exactaly what you want to accomplish nor what errors you are experiencing, I just fixed some logic an sintax.
As it is, the code will append the ssid data to your csv only if quality is better than 30.
Let me know if that is what you want.
def wifiscan():
ssid = []
scanoutput = check_output(["iwlist", "wlan0", "scan"])
curtime = time.strftime("%I:%M:%S")
ssid.append(curtime)
quality = 0
essid = ""
for line in scanoutput.split('\n'):
line=str(line)
if line.startswith("Quality"):
quality=int(line[8:-25])
if quality>30 and line.startswith("ESSID"):
line=line[7:-1]
ssid.append(quality)
ssid.append(line)
with open('/home/pi/Desktop/Project/Results/'+'test.csv','a') as csvfile:
csvwriter = csv.writer(csvfile,delimiter=',')
csvwriter.writerow(ssid)
print ssid
Note that the code is sensible to any change in the sintax of the input you provide.
Also, to avoid syntax change issues in your input, maybe you should read about regular expressions in python: https://docs.python.org/2/howto/regex.html

Related

Paramiko not receiving all data from Channel

I've done a script to configure a couple of ASA devices. It does the job perfectly BUT I can't get the whole output from the devices I'm configuring, at some point the data gets stucked and there's no more output. I want to have that in order to check for problems or misconfigurations, etc. I'm configuring around 500 IPs, objects, groups, etc. from files on ASA firewalls... I don't know what to do, I haven't found any command to clean or erase Paramiko's buffer :(
Any ideas? This is my code:
import paramiko
import re
import time
from tqdm.auto import tqdm
from io import StringIO
device_ip = 'X.X.X.X'
ssh = paramiko.SSHClient() # Connection
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname = device_ip, username = username, password = password)
connection = ssh.invoke_shell()
output_data = StringIO()
connection.send("conf t\n") # Enter configuration mode
time.sleep(1)
file = open(file_name, 'r') # IP list file
lines = file.readlines()
objects = []
ip_subnet = re.compile(r'([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/([0-9]+)')
group_name = "GRP-OBJ-EU-Blablabla"
for line in tqdm(lines):
match = ip_subnet.findall(line.strip())
ip = match[0][0]
subnet = match[0][1] # Not used, for future use may be...
object_name = "obj-"+ip
object_configuration = "object network "+object_name
object_network = "host "+ip
object_description = "description whatever"
objects.append(object_name)
connection.send(object_configuration+"\n")
time.sleep(1)
connection.send(object_network+"\n")
time.sleep(1)
connection.send(object_description+"\n")
time.sleep(1)
received_data = connection.recv(5000).decode(encoding='utf-8')
if received_data:
output_data.write(received_data)
group_command = "object-group network "+group_name
connection.send(group_command+"\n")
time.sleep(1)
for object_host in tqdm(objects):
connection.send("network-object object "+object_host+"\n")
time.sleep(1)
received_data = connection.recv(5000).decode(encoding='utf-8')
if received_data:
output_data.write(received_data)
connection.send("end \n")
time.sleep(1)
connection.send("wr \n")
time.sleep(5)
connection.close()
ssh.close()
file.close()
print(output_data)
I've tried a line like this one below but it does not work either:
device_output = connection.recv(1000000000000).decode(encoding='utf-8')
I could not directly test your code, but I had a similar problem in the past and found a practical solution. To get all the data at once, you can open a notepad and print the received_data data in it. You can also use ascii outside of the encoding='utf-8' method.
Example Code:
received_data = remote_connection.recv(99999999)
result = received_data.decode('ascii').strip("\n")
LOGfile = "log.txt"
log = open(LOGfile, 'a')
log.write(result )
log.close()
I recommend Netmiko-TTP library to parse all the data you want except the Paramiko library. I have given a sample code link below. I hope that will be useful.
https://github.com/MertKulac/Nokia--TTP--Template--Command--Set/blob/main/show%20system%20informtaion.py
Well I've found the solution... it's pretty dumb. I was not exiting enable mode... and it seems that was it! lol I don't get the relation but anyways the lines below work... Thanks everyone for your help!
....
connection.send("end \n")
time.sleep(1)
connection.send("wr \n")
time.sleep(5)
device_output = connection.recv(10000000).decode(encoding='utf-8')
connection.close()
ssh.close()
file.close()
print(device_output)

Changing output of speedtest.py and speedtest-cli to include IP address in output .csv file

I added a line in the python code “speedtest.py” that I found at pimylifeup.com. I hoped it would allow me to track the internet provider and IP address along with all the other speed information his code provides. But when I execute it, the code only grabs the next word after the find all call. I would also like it to return the IP address that appears after the provider. I have attached the code below. Can you help me modify it to return what I am looking for.
Here is an example what is returned by speedtest-cli
$ speedtest-cli
Retrieving speedtest.net configuration...
Testing from Biglobe (111.111.111.111)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by GLBB Japan (Naha) [51.24 km]: 118.566 ms
Testing download speed................................................................................
Download: 4.00 Mbit/s
Testing upload speed......................................................................................................
Upload: 13.19 Mbit/s
$
And this is an example of what it is being returned by speediest.py to my .csv file
Date,Time,Ping,Download (Mbit/s),Upload(Mbit/s),myip
05/30/20,12:47,76.391,12.28,19.43,Biglobe
This is what I want it to return.
Date,Time,Ping,Download (Mbit/s),Upload (Mbit/s),myip
05/30/20,12:31,75.158,14.29,19.54,Biglobe 111.111.111.111
Or may be,
05/30/20,12:31,75.158,14.29,19.54,Biglobe,111.111.111.111
Here is the code that I am using. And thank you for any help you can provide.
import os
import re
import subprocess
import time
response = subprocess.Popen(‘/usr/local/bin/speedtest-cli’, shell=True, stdout=subprocess.PIPE).stdout.read().decode(‘utf-8’)
ping = re.findall(‘km]:\s(.*?)\s’, response, re.MULTILINE)
download = re.findall(‘Download:\s(.*?)\s’, response, re.MULTILINE)
upload = re.findall(‘Upload:\s(.*?)\s’, response, re.MULTILINE)
myip = re.findall(‘from\s(.*?)\s’, response, re.MULTILINE)
ping = ping[0].replace(‘,’, ‘.’)
download = download[0].replace(‘,’, ‘.’)
upload = upload[0].replace(‘,’, ‘.’)
myip = myip[0]
try:
f = open(‘/home/pi/speedtest/speedtestz.csv’, ‘a+’)
if os.stat(‘/home/pi/speedtest/speedtestz.csv’).st_size == 0:
f.write(‘Date,Time,Ping,Download (Mbit/s),Upload (Mbit/s),myip\r\n’)
except:
pass
f.write(‘{},{},{},{},{},{}\r\n’.format(time.strftime(‘%m/%d/%y’), time.strftime(‘%H:%M’), ping, download, upload, myip))
Let me know if this works for you, it should do everything you're looking for
#!/usr/local/env python
import os
import csv
import time
import subprocess
from decimal import *
file_path = '/home/pi/speedtest/speedtestz.csv'
def format_speed(bits_string):
""" changes string bit/s to megabits/s and rounds to two decimal places """
return (Decimal(bits_string) / 1000000).quantize(Decimal('.01'), rounding=ROUND_UP)
def write_csv(row):
""" writes a header row if one does not exist and test result row """
# straight from csv man page
# see: https://docs.python.org/3/library/csv.html
with open(file_path, 'a+', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',', quotechar='"')
if os.stat(file_path).st_size == 0:
writer.writerow(['Date','Time','Ping','Download (Mbit/s)','Upload (Mbit/s)','myip'])
writer.writerow(row)
response = subprocess.run(['/usr/local/bin/speedtest-cli', '--csv'], capture_output=True, encoding='utf-8')
# if speedtest-cli exited with no errors / ran successfully
if response.returncode == 0:
# from the csv man page
# "And while the module doesn’t directly support parsing strings, it can easily be done"
# this will remove quotes and spaces vs doing a string split on ','
# csv.reader returns an iterator, so we turn that into a list
cols = list(csv.reader([response.stdout]))[0]
# turns 13.45 ping to 13
ping = Decimal(cols[5]).quantize(Decimal('1.'))
# speedtest-cli --csv returns speed in bits/s, convert to bytes
download = format_speed(cols[6])
upload = format_speed(cols[7])
ip = cols[9]
date = time.strftime('%m/%d/%y')
time = time.strftime('%H:%M')
write_csv([date,time,ping,download,upload,ip])
else:
print('speedtest-cli returned error: %s' % response.stderr)
$/usr/local/bin/speedtest-cli --csv-header > speedtestz.csv
$/usr/local/bin/speedtest-cli --csv >> speedtestz.csv
output:
Server ID,Sponsor,Server Name,Timestamp,Distance,Ping,Download,Upload,Share,IP Address
Does that not get you what you're looking for? Run the first command once to create the csv with header row. Then subsequent runs are done with the append '>>` operator, and that'll add a test result row each time you run it
Doing all of those regexs will bite you if they or a library that they depend on decides to change their debugging output format
Plenty of ways to do it though. Hope this helps

regex to grep string from config file in python

I have config file which contains network configurations something like given below.
LISTEN=192.168.180.1 #the network which listen the traffic
NETMASK=255.255.0.0
DOMAIN =test.com
Need to grep the values from the config. the following is my current code.
import re
with open('config.txt') as f:
data = f.read()
listen = re.findall('LISTEN=(.*)',data)
print listen
the variable listen contains
192.168.180.1 #the network which listen the traffic
but I no need the commented information but sometimes comments may not exist like other "NETMASK"
If you really want to this using regular expressions I would suggest changing it to LISTEN=([^#$]+)
Which should match anything up to the pound sign opening the comment or a newline character.
I come up with solution which will have common regex and replace "#".
import re
data = '''
LISTEN=192.168.180.1 #the network which listen the traffic
NETMASK=255.255.0.0
DOMAIN =test.com
'''
#Common regex to get all values
match = re.findall(r'.*=(.*)#*',data)
print "Total match found"
print match
#Remove # part if any
for index,val in enumerate(match):
if "#" in val:
val = (val.split("#")[0]).strip()
match[index] = val
print "Match after removing #"
print match
Output :
Total match found
['192.168.180.1 #the network which listen the traffic', '255.255.0.0', 'test.com']
Match after removing #
['192.168.180.1', '255.255.0.0', 'test.com']
data = """LISTEN=192.168.180.1 #the network which listen the traffic"""
import re
print(re.search(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', data).group())
>>>192.168.180.1
print(re.search(r'[0-9]+(?:\.[0-9]+){3}', data).group())
>>>192.168.180.1
In my experience regex is slow runtime and not very readable. I would do:
with open('config.txt') as f:
for line in f:
if not line.startswith("LISTEN="):
continue
rest = line.split("=", 1)[1]
nocomment = rest.split("#", 1)[0]
print nocomment
I think the better approach is to read the whole file as the format it is given in. I wrote a couple of tutorials, e.g. for YAML, CSV, JSON.
It looks as if this is an INI file.
Example Code
Example INI file
INI files need a header. I assume it is network:
[network]
LISTEN=192.168.180.1 #the network which listen the traffic
NETMASK=255.255.0.0
DOMAIN =test.com
Python 2
#!/usr/bin/env python
import ConfigParser
import io
# Load the configuration file
with open("config.ini") as f:
sample_config = f.read()
config = ConfigParser.RawConfigParser(allow_no_value=True)
config.readfp(io.BytesIO(sample_config))
# List all contents
print("List all contents")
for section in config.sections():
print("Section: %s" % section)
for options in config.options(section):
print("x %s:::%s:::%s" % (options,
config.get(section, options),
str(type(options))))
# Print some contents
print("\nPrint some contents")
print(config.get('other', 'use_anonymous')) # Just get the value
Python 3
Look at configparser:
#!/usr/bin/env python
import configparser
# Load the configuration file
config = configparser.RawConfigParser(allow_no_value=True)
with open("config.ini") as f:
config.readfp(f)
# Print some contents
print(config.get('network', 'LISTEN'))
gives:
192.168.180.1 #the network which listen the traffic
Hence you need to parse that value as well, as INI seems not to know #-comments.

Python Socket Wireless scan strange output

i have this code here:
import socket
raw = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
raw.bind(("mon0", 0x0003))
ap_list = set()
out = open("out.cap", 'w')
while True:
pkt = raw.recvfrom(2048)[0]
if pkt[36:42] not in ap_list:
ap_list.add(pkt[36:42])
print (pkt)
out.writelines(str(pkt))
but the output is kinda strange to me. how to make it Human readable?
Example of output:
b'\x00!c\xf60\xbe\x807s\xa8\xe5#\x08\x00E\x00\x004\xea\xec#\x00$\x06\xd2\xcck\x15mA\xc0\xa8\x00\x0c\x00P\x90\xee\x9dx\xd9E=\xfd;[\x80\x10\x00no\xc0\x00\x00\x01\x01\x08\n)\xa0w\x10\x00\xd6J\xa8'
Update:
using this
decoded = pkt.decode("ISO-8859-1")
i've managed to do what i need but wireshark don't read my output file very well and i also need to remove useless data from the output
some help?
this is the new code:
import socket
import sys
raw = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
raw.bind((sys.argv[1], 0x0003))
ap_list = set()
out = open("out.cap", 'w')
while True:
pkt = raw.recvfrom(1024)[0]
if pkt[36:42] not in ap_list:
ap_list.add(pkt[36:42])
decoded = pkt.decode("ISO-8859-1")
print(str(pkt[0:20]).split("'")[1])
out.writelines(str(decoded) + "\n")
In Wireshark you should be able to see what protocols are being used. Then you can parse them, for example using the scapy package.
– John Zwinck

SecureCRT python scripting

I'm writing a script that will find out what router model and what IOS version a Cisco router is using. I'm writing it in Python using the SecureCRT api. The script sends a show version command that displays information about the router, including the information I need. I then use the SecureCRT api to pull all of that text from the application screen and then I iterate through the text to and use if statements to match router models to see which one it is. Everytime i run the script it runs and doesnt error out but the "new.txt" file is blank.
# $language = "python"
# $interface = "1.0"
crt.Screen.Synchronous = True
ModelIOSScreen = ""
def Main():
ModelIOS()
def ModelIOS():
crt.Screen.Send("show version" + chr(13))
crt.Screen.WaitForString(">")
Screen = crt.Screen.Get(-1, 1, 50, 70)
ModelIOSScreen = str(Screen.split(" ", -1))
RouterModel = ""
for word in ModelIOSScreen:
if word == "2811":
RouterModel = "2811"
elif word == "2801":
RouterModel = "2801"
elif word == "CISCO2911/K9":
RouterModel = "2911"
file = open("new.txt", "w")
file.write(ModelIOSScreen)
I'm on my phone and could probably write a better answer, but I'm about to go to bed. You never close the file you open. Using the following works better.
with open(file, "w") as fp:
fp.write(variable)

Categories

Resources