Cross-eit.py
This script fetches EPG data for specified channels from a mythtv database and exports this data to an XMLTV [1] formatted XML file.
The purpose of this is to extract EPG from channels with good data, and use this data to populate other channels where no data is available.
The program needs the following arguments: ./cross-eit.py chanid1,xmlid1 chanid2,xmlid2 chanidN,xmlidN XMLTV-export-file.xml
To check the channel numbers for the channels you want to extract EPG from, run the following command: mysql -u mythtv -p mythconverg -e "SELECT chanid,callsign from channel WHERE callsign='channel name'"
If you want to import the EPG data from the xml file using mythfilldatabase, you must add the appropriate xmltvid for each channel you want to import EPG to in mythweb [2] as well as uncheck the useonairguide for these channels.
Example: (assuming sourceid of 1 for mythtv) ./cross-eit.py 1004,tv2.guide 1108,history.guide 1022,natgeo.guide export.xml mythfilldatabase -v xmltv --file 1 export.xml
[1] http://wiki.xmltv.org/index.php/XMLTVFormat [2] http://localhost/mythweb/settings/tv/channels
#!/usr/bin/env python # -*- coding: utf8 -*- """ This program fetches schedule information from a mythtv database and exports this data to an XMLTV formatted XML file. check def help(): for further description """ import os import datetime import time import MySQLdb import sys from string import split from xml.etree.ElementTree import Element, SubElement, tostring from xml.dom import minidom def help(): print("Script description:\n\n" "This script fetches EPG data for specified channels from a mythtv database and exports this data to an XMLTV [1] " "formatted XML file.\n\n" "The purpose of this is to extract EPG from channels with good data,\n" "and use this data to populate other channels where no data is available.\n\n" "The program needs the following arguments:\n" "\t./cross-eit.py chanid1,xmlid1 chanid2,xmlid2 chanidN,xmlidN XMLTV-export-file.xml\n\n" "To check the channel numbers for the channels you want to extract EPG from, run the following command:\n" "mysql -u mythtv -p mythconverg -e \"SELECT chanid,callsign from channel WHERE callsign='channel name'\"\n\n" "If you want to import the EPG data from the xml file using mythfilldatabase, \n" "you must add the appropriate xmltvid for each channel you want to import EPG to in mythweb [2] as well as uncheck the useonairguide for these channels.\n\n" "Example: (assuming sourceid of 1 for mythtv)\n" "\t./cross-eit.py 1004,tv2.guide 1108,history.guide 1022,natgeo.guide export.xml\n" "\tmythfilldatabase -v xmltv --file 1 export.xml\n\n" "[1] http://wiki.xmltv.org/index.php/XMLTVFormat\n" "[2] http://localhost/mythweb/settings/tv/channels") def d2s(dateobj): """ Reads dateobject and returns a string in XLMTV format with timezone offset. """ date = dateobj + datetime.timedelta(seconds=time.timezone) return date.strftime("%Y%m%d%H%M%S") def read_config_xml(): """Reads in and parses a config.xml from a number of places: 1) /etc/mythtv/config.xml 2) /usr/share/mythtv/config.xml """ dictionary={"doc": None, 'DBHostName': None, 'DBUserName': None, 'DBPassword': None, 'DBName': None, 'SecurityPin' : None} for file in ['/etc/mythtv/config.xml', '/usr/share/mythtv/config.xml' ]: if file and os.path.exists(file): dictionary["doc"]=minidom.parse(file) for tag in dictionary: elements=dictionary["doc"].getElementsByTagName(tag) if elements: dictionary[tag]=elements[0].childNodes[0].data break return dictionary """ Main script """ version = "v1.0" print "Cross-Eit %s\n" % (version) #Read and check arguments if len(sys.argv) == 1: print "Error: No arguments specified. Aborting...\n" help() sys.exit() elif sys.argv[1] == "-h" or sys.argv[1] == "--help" or sys.argv[1] == "-?": help() sys.exit() channels = {} for idx,val in enumerate(sys.argv): if idx == 0: pass elif idx == (len(sys.argv)-1): xmlfile=val else: s = val.split(",") if len(s) <> 2: print "Error: Not able to parse argument %s. Aborting...\n" % (s) help() sys.exit() try: testint=int(s[0]) except: print "Error: Channel number is not an integer - check you syntax. Aborting...\n" help() sys.exit() if len(s[1]) == 0: print "XMLTVID is not specified for channel %s. Aborting...\n" % (s[0]) help() sys.exit() channels[s[0]]=s[1] #create xml object "tv" tv = Element('tv') # Read local config and connect to database mysqlconn=read_config_xml() conn = MySQLdb.connect (host = mysqlconn['DBHostName'], user = mysqlconn['DBUserName'], passwd = mysqlconn['DBPassword'], db = mysqlconn['DBName']) cursor = conn.cursor(MySQLdb.cursors.DictCursor) #Read schedule for each channel and create XML elements for chan in channels.keys(): print "Processing channel number: %s, XMLTV id: %s" % (chan, channels[chan]) cursor.execute("SELECT starttime, endtime, title, subtitle, description, category, previouslyshown FROM program WHERE chanid=%s", chan) result_set = cursor.fetchall() #Read each row for channel 'chan' for row in result_set: program = SubElement(tv, 'programme', channel=channels[chan], start=d2s(row["starttime"]), stop=d2s(row["endtime"])) title = SubElement(program, 'title') title.text=row["title"] subtitle = SubElement(program, 'sub-title') subtitle.text=row["subtitle"] desc = SubElement(program, 'desc') desc.text=row["description"] category = SubElement(program, 'category') category.text=row["category"] if int(row["previouslyshown"]) == 1: #previsously shown prev=SubElement(program, 'previously-shown') print "Number of processed programs: %d" % cursor.rowcount cursor.close() print "Writing XML file %s" % (xmlfile) f = open(xmlfile, "w") #Create XML file and header f.write('<?xml version="1.0" ?>\n') f.write('<!DOCTYPE tv SYSTEM "xmltv.dtd">\n') #write tv XML element including all program subelements f.write(tostring(tv)) f.close()