user3211229
user3211229

Reputation: 111

Python Regex Google App Engine

I'm using python on GAE

I'm trying to get the following from html

<TD><FONT FACE="Arial,helvetica" SIZE="-2">V1068078</FONT></TD>

I want to get everything that will have a "V" followed by 7 or more digits and have behind it.

My regex is

response = urllib2.urlopen(url)
html = response.read()
tree = etree.HTML(html)
mls = tree.xpath('/[V]\d{7,10}</FONT>')
self.response.out.write(mls)

It's throwing out an invalid expression. I don't know what part of it is invalid because it works on the online regex tester

How can i do this in the xpath format?

Upvotes: 2

Views: 240

Answers (6)

hwnd
hwnd

Reputation: 70732

How can I do this in the XPath?

You can use starts-with() here.

>>> from lxml import etree
>>> html = '<TD><FONT FACE="Arial,helvetica" SIZE="-2">V1068078</FONT></TD>'
>>> tree = etree.fromstring(html)
>>> mls  = tree.xpath("//TD/FONT[starts-with(text(),'V')]")[0].text
'V1068078'

Or you can use a regular expression

>>> from lxml import etree
>>> html = '<TD><FONT FACE="Arial,helvetica" SIZE="-2">V1068078</FONT></TD>'
>>> tree = etree.fromstring(html)
>>> mls  = tree.xpath("//TD/FONT[re:match(text(), 'V\d{7,}')]", 
           namespaces={'re': 'http://exslt.org/regular-expressions'})[0].text
'V1068078'

Upvotes: 2

ncemami
ncemami

Reputation: 439

For everyone that keeps posting purely regex solutions, you need to read the question -- the problem is not just formulating a regular expression; it is an issue of isolating the right nodes of the XML/HTML document tree, upon which regex can be employed to subsequently isolate the desired strings.

You didn't show any of your import statements -- are you trying to use ElementTree? In order to use ElementTree you need to have some understanding of the structure of your XML/HTML, from the root down to the target tag (in your case, "TD/FONT"). Next you would use the ElementTree methods, "find" and "findall" to traverse the tree and get to your desired tags/attributes.

As has been noted previously, "ElementTree uses its own path syntax, which is more or less a subset of xpath. If you want an ElementTree compatible library with full xpath support, try lxml." ElementTree does have support for xpath, but not the way you are using it here.

If you indeed do want to use ElementTree, you should provide an example of the html you are trying to parse so everybody has a notion of the structure. In the absence of such an example, a made up example would look like the following:

import xml, urllib2
from xml.etree import ElementTree


url = "http://www.uniprot.org/uniprot/P04637.xml"
response = urllib2.urlopen(url)
html = response.read()
tree = xml.etree.ElementTree.fromstring(html)
# namespace prefix, see https://stackoverflow.com/questions/1249876/alter-namespace-prefixing-with-elementtree-in-python
ns = '{http://uniprot.org/uniprot}'
root = tree.getiterator(ns+'uniprot')[0]
taxa = root.find(ns+'entry').find(ns+'organism').find(ns+'lineage').findall(ns+'taxon')
for taxon in taxa:
  print taxon.text

# Output:
Eukaryota
Metazoa
Chordata
Craniata
Vertebrata
Euteleostomi
Mammalia
Eutheria
Euarchontoglires
Primates
Haplorrhini
Catarrhini
Hominidae
Homo

Upvotes: 1

Avinash Raj
Avinash Raj

Reputation: 174756

And the one without capturing groups.

>>> import re
>>> str = '<TD><FONT FACE="Arial,helvetica" SIZE="-2">V1068078</FONT></TD>'
>>> m = re.search(r'(?<=>)V\d{7}', str)
>>> print m.group(0)
V1068078

Upvotes: 0

Suku
Suku

Reputation: 3880

>>> import re

>>> s = '<TD><FONT FACE="Arial,helvetica" SIZE="-2">V1068078</FONT></TD>'

>>> a = re.search(r'(.*)(V[0-9]{7,})',s)

>>> a.group(2)
'V1068078'

EDIT

(.*) is a greedy method. re.search(r'V[0-9]{7,}',s) will do the extraction with out greed.

EDIT as @Kaneg said, you can use findall for all instances. You will get a list with all occurrences of 'V[0-9]{7,}'

Upvotes: 2

Martin Konecny
Martin Konecny

Reputation: 59651

The following will work:

result = re.search(r'V\d{7,}',s)
print result.group(0)  # prints 'V1068078'

It will match any string of numeric digit of length 7 or more that follows the letter V

EDIT

If you want it to find all instances, replace search with findall

s = '<TD><FONT FACE="Arial,helvetica" SIZE="-2">V1068078</FONT></TD>V1068078   V1068078   V1068078'
re.search(r'V\d{7,}',s)
['V1068078', 'V1068078', 'V1068078', 'V1068078']

Upvotes: 1

Kaneg
Kaneg

Reputation: 515

Below example can match multiple cases:

import re
s = '<TD><FONT FACE="Arial,helvetica" SIZE="-2">V10683333</FONT></TD>,' \
' <TD><FONT FACE="Arial,helvetica" SIZE="-2">V1068333333</FONT></TD>'
m = re.findall(r'V\d{7,}', s)
print m

Upvotes: 1

Related Questions