Package: lieparse
lieparseis HTML parser ant text retriever using user defined rule set.HISTORYLibrary was initially written for Vilnius UniversityLiepa-2project. AlthoughLIEPAis an abbreviation of project name, in LithuanianLiepameans “Linden tree”. The tree image is in projects logotype also.QUICK USAGELets say you have HTML markup text read into string HtmlText.
Then to retrieve all text from division with id=”main” you need to:from lieparse import lieParser
rules = '<div id="main">$Data[]</div> ::$Data[];'
parser = lieParser(rules)
parser.feed(HtmlText)
parser.close()More sophisticated example can be found after rules syntax definitionsRULES SYNTAXRules consist of statements optionally separated by white space.White space is considered space, tab, new line and comment.Comment begins from#sign and lasts to line end. (Concretely regex matchr'(?:\s*(?:#.*?\n)?)*\s*')Statements can contain incorporated statements and data definitions.Statements are:Rep statementloops matching all incorporated statements:#(<<other statements>>)
#+(<<other statements>>)
*(<<other statements>>)where:# is optional numeric value and means repeat count
+ is one-or-more modifier. If standing alone it is the same as 1+
* is zero-or-more modifier. Cannot be preceded by numberIf*modifier was specified or when+modified statement reaches zero count, statement exits on first match of logical statements followingRepconstruct (or of course after enclosingTagends). In version 1.1.x suchBreakstatement has higher priority than internalRepstatements. Earlier if same statement matched asRepor asBreakit was considered as a part ofRepstatement.If number or+,*modifiers are found before other statements (TagorAny), repeat block is generated automatically. So writing'2<div></div>'is automatically converted to'2(<div></div>)'.Any statementmatches any of incorporated statements:{<<other statements>>}Any-match is done by statements definition order until first one matches. Statement can containAny,TagorRepstatements.Printstatement is not allowed here.Tag statementmain matching statement the html text is checked onto:<name attr="string" $aData[<<aData attrs>>] >
    <<filterStr>> $Data[<<Data attrs>>] <<other statements>>
</name>where:name is tag name, something like 'div', 'li', 'span'.

attr is optional and optionally multiple attribute that must be present in html
   tag to be matched. Real tag must contain all, but maybe not only, specified attributes
   to match this rule. If attribute in html tag has no value, in rule it must be
   specified with empty string as a value.

class="" attribute is split by whitespace into sets while parsing rule as well
   as while parsing html. Rule attribute set must be html attribute subset to match.

style="" attribute is handled similarly, but splitting on ';' and replacing
   multiple white space to single space and stripping spaces before adding to set.

$aData is optional and optionally multiple attribute data definition. Can be
   indirect data ($*data[]) also. Definition follows. Data variable name must
   insensitive match regular expression ``'[a-z]+[a-z0-9_]*'``

filterStr is optional tag data filtering string. If enclosed in '/' marks -
   regular expression match is performed against Tag data. If simple string -
   full match is performed (i.e. "My data" is equivalent to "/^My data$/").
   If tag data is not matched - tag is considered not matching.

$Data is optional and optionally multiple data collection attribute. Can be
   indirect data ($*data[]) or to-first-tag data ($data[!]) or both.Statement can incorporate other statements (Rep,Any,Tag,Print) mixed with$DatadefinitionsPrint statementonly facility to output gathered data::<<flags>> <<loopDef>>:<<"string">> $pData[<<pData attrs>>] <<Other print statements>> ;where:flags is optional print behavior modifiers - string (no quotes) containing one or
   more flag letters. Next flags are defined:

   n - print new line after full print statement
   N - print new line after each individual loop of print statement
   s - separate each print value with space
   U - convert output to UPERCASE
   u - capitalize output words
   l - convert output to lowercase
   A - redirect output to stream A, can be specified, defaults to sys/stdout
   B - redirect output to stream B, can be specified, defaults to sys/stdout
   C - redirect output to stream C, can be specified, defaults to sys/stdout
     stream parameters are spread to child items but child item can have stream redefined

loopDef is expression defining how much times print body will be performed. If not
   specified it defaults to 1. If defined - it is counted at run time depending
   on real data. Loop counter is from 0 up-to loopDef. On run time current loop counter
   can be accessed in index expressions as $0. Outer loop statements counter is
   accessible as $1 for first surrounding print statement, $2 for second and so on, the
   last being ourselves (so same as $0).

loopDef can be one of next:

   indexExpr - countable expression (look below) with $# as surrounding
      loop counters, numbers, parenthesis, arithmetic operations '+', '-', '*'
      and (form version 1.1.0) C-style ternary operators.

   empty - index is set to 1

string is optional string that will be printed

pData is data variable name (can be indirect: $*pData) from which data will be printed.
   Full definition is below.string, pData and other print statements can be freely mixed inside print statement body.Index ExpressionsindexExpr- countable expression, that can be used in print statement loop definition and in pData (print statement data) definition. It is countable expression with $# as surrounding loop counters, $<<name>> or $*<<name>> as variable array length, numbers, parenthesis and arithmetic operations+,-,*.Valid indexExpr’s:3
$2 + 1
($1 + 1) * 2
$Data - 1Data DefinitionsDatadefinitions can be found insideTagdefinition (aData), insideTagbody (dData and xData) and print statement (pData). Data reference (without []) can be found in print loopDef.pDatacan not be modified - information is only retrieved from named variable. Other types of Data is dedicated to collect data from tag attributes or html text.All data variables are arrays. After definition (even if it occurs with+sign) array pointer is 0. Pointer can be incremented by+sign in variable attributes. Pointer can never be decremented.-sign in attributes clears variable data, leaving index unchanged.!in attributes defines xData instead of dData.Variables can be direct:$<<name>>[<<attr>>]- defines variable named <<name>>and indirect:$*<<name>>[<<attr>>]- here name of variable is kept in last element of array$<<name>>[]Only one level of indirection is allowed.<<attr>>and behavior differs depending on variable scope (aData, dData, xData or pData). However in all scopes accessed data is same for same named variable.For aData, dData and xData:<<attr>>consists of optional flag with values!,+or-and optional space separated strings.If flag is:'!' - xData type variable is defined. Valid only for variables inside Tag body.

'+' - index value is incremented before other operations. The exception is if variable is
      first time defined - in this case index is left 0.

'-' - all data accumulated in variable by current index is cleared before other operations.When no flag is present, data is appended to variable by current index.String can be enclosed in double quotation marks. This allows strings with spaces. If no strings are defined - passed data is simply added to variable.String can be:/<<match>>/         - if passed data not matches regular expression it is ignored.
      All other strings are not processed

/<<find>>/<<repl>>/ - if <<find>> regular expression matches passed data, it is
      replaced with <<repl>> and got data added to variable. On no match - data is
      ignored. Other strings are processed with all data passed to them.

+/<<find>>/<<repl>>/ - if <<find>> regular expression matches passed data, it is
      replaced with <<repl>> and got data added to variable. On no match - original
      data is added to variable. Always must be enclosed in quotation marks. New in 1.1.0.
      After replace other processing strings (if any) get replaced, not original data.

@<<attrName>>       - Value of specified Tag attribute is added to variable.

<<otherString>>     - specified string is added to variable.Data passed to variables is:aData - all Tag attributes with names as name="value". If there is some class values
      they are passed as separate class="value" pairs.

dData - all accumulated data in this and above Tag levels.

xData - all accumulated data up to first sub-tag match.For pData<<attr>>can be one of next forms:<<indexExpr0>>;<<indexExpr>><<regexps>>- for indirect variables onlyor<<indexExpr>> <<regexps>>- for all variableswhere:<<indexExpr>> - is optional array index value at which will be printed. If not specified
      defaults to $0

<<indexExpr0>> - is optional parent array index from which variable name is taken.
      Defaults to $0.

<<regexps>> is optional regular expressions in form /<<find>>/<<repl>>/
      All expressions are applied to data value before print by order of appearance.SYSTEM VARIABLESFrom version 1.1.0 we have defined some global system variables. If found anywhere in text variable
name is replaced with it’s value. You can use command line (or #!flags) option –no-vars-expand
if such behavior is undesirable. Another workaround is shown in example lieparse3_rule.txt
based on extracting data from this chapter.Defined system variables:$URL       -  full URL of site we are examining
$PROTO     -  protocol of site (http:// or https://)
$BASEURL   -  base URL of site
$BASEURLNP -  base URL of site without port number. If no port specified - same as $BASEURL
$PORT      -  port number. If not specified, empty string
$DATE      -  date the extracting program is being run (as returned by strftime("%x"))
$TIME      -  time, program is running (as returned by strftime("%X"))
$DATETIME  -  date and time, program is running (as returned by strftime("%c"))Parsing parameters inside rules fileStarting with version 1.1.0 you can define parsing parameters inside rules file.Older versions treats this as comment.Syntax is:#!<<parametername>> <<space separated parameter values>>Do not define parameters in first file line - Linux shell will treat that as executable file definition.Next parameters are recognized:url      -  location to parse URL
href     -  same as above. If both specified, first found is used
winurl   -  URL for Windows systems. Normally used with file:// references
winhref  -  same as above
linurl   -  URL for Linux systems. Normally used with file:// references
linhref  -  same as above
usragent -  user agent. Can be specified by name or by value
fromurl  -  set URL we are coming from
flags    -  specify list of space separated behavior flags. Next are defined:
   ssl-verify, dump-rules, dump-vars, dump-json, dump-json-np, no-vars-expand
output-file[ABCE]? see LiepaParse -h for definition
time-locale - specify locale for system time variables $DATE, $DATETIME and $TIMEADVANCED EXAMPLEWe will retrieve python library names from docs.python.org site:import sys
from lieparse import lieParser
from pycurl import Curl, global_init, global_cleanup, GLOBAL_ALL
usragent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0"
url = "https://docs.python.org/3.6/py-modindex.html"
rules = r'''
<table class="indextable modindextable">
    *<code class="xref">
        $Data[+]
    </code>
</table>
:N $Data:$Data[];     # if flags are ns we will have space separated list
'''

global_init(pycurl.GLOBAL_ALL)
c = Curl()
c.setopt(c.USERAGENT, usragent)
c.setopt(c.SSL_VERIFYPEER, 0)      # have problems verifying certificate under Windows
c.setopt(c.URL, url)
s = c.perform_rs()
global_cleanup()

parser = lieParser(rules)
parser.feed(s)
v = parser.close()
if v != 0:
    print("Unmatched {} items".format(v), file=sys.stderr)SummaryAuthor:Vidmantas Balčytis <vidma@lema.lt>Version:1.1.0 (2020-03-03)Changes:1.0.0- 1.0.4 versions released have same code base and differs only in documentation1.0.5bug fix looping all rules after full matchbug fix retrieving attribute datasyntax and value error no more prints tracebackadded testing script LiepaParse and samples1.1.0 major service release, compatible with rules written for older versions.breaking statement from zero-or-moreReploop has now greater priority than internalRep statement. thats why some rules written for 1.1.x may not run on 1.0.x. Backwards compatibility is ensured.Index Expressionsnow can have $<<var name>> and $*<<var name>> as operands. Also C-style ternary operations were added.Print statementnew flags are introducedformating now is preserved in <pre> tagsSYSTEM VARIABLESand their expansion is introducedadded find/replace string with keep-on-not-found type in data variables.Parsing parameters inside rules fileis introduced.