Python анализирует определенные данные в таблице html, используя lxml и xpath

Прежде всего, я новичок в python и Stack Overflow, поэтому, пожалуйста, будьте добры.

Это исходный код html-страницы, из которой я хочу извлечь данные.

Веб-страница: http://gbgfotboll.se/information/?scr=table&ftid=51168 Таблица находится внизу страницы

  <html>
        table class="clCommonGrid" cellspacing="0">
                <thead>
                    <tr>
                        <td colspan="3">Kommande matcher</td>
                    </tr>
                    <tr>
                        <th style="width:1%;">Tid</th>
                        <th style="width:69%;">Match</th>
                        <th style="width:30%;">Arena</th>
                    </tr>
                </thead>

                <tbody class="clGrid">

            <tr class="clTrOdd">
                <td nowrap="nowrap" class="no-line-through">
                    <span class="matchTid"><span>2014-09-26<!-- br ok --> 19:30</span></span>



                </td>
                <td><a href="?scr=result&amp;fmid=2669197">Guldhedens IK - IF Warta</a></td>
                <td><a href="?scr=venue&amp;faid=847">Guldheden Södra 1 Konstgräs</a> </td>
            </tr>

            <tr class="clTrEven">
                <td nowrap="nowrap" class="no-line-through">
                    <span class="matchTid"><span>2014-09-26<!-- br ok --> 13:00</span></span>



                </td>
                <td><a href="?scr=result&amp;fmid=2669176">Romelanda UF - IK Virgo</a></td>
                <td><a href="?scr=venue&amp;faid=941">Romevi 1 Gräs</a> </td>
            </tr>

            <tr class="clTrOdd">
            <td nowrap="nowrap" class="no-line-through">
                <span class="matchTid"><span>2014-09-27<!-- br ok --> 13:00</span></span>



            </td>
            <td><a href="?scr=result&amp;fmid=2669167">Kode IF - IK Kongahälla</a></td>
            <td><a href="?scr=venue&amp;faid=912">Kode IP 1 Gräs</a> </td>
        </tr>

        <tr class="clTrEven">
            <td nowrap="nowrap" class="no-line-through">
                <span class="matchTid"><span>2014-09-27<!-- br ok --> 14:00</span></span>



            </td>
            <td><a href="?scr=result&amp;fmid=2669147">Floda BoIF - Partille IF FK </a></td>
            <td><a href="?scr=venue&amp;faid=218">Flodala IP 1</a> </td>
        </tr>


                </tbody>
        </table>
    </html>

Мне нужно извлечь время: 19:30 и название команды: Guldhedens IK - IF Warta, что означает первую и вторую ячейку таблицы (не третью) из первой строки таблицы и 13:00/Romelanda UF - IK Virgo из вторая строка таблицы и т. д. из всех строк таблицы.

Как вы можете видеть, каждая строка таблицы имеет дату прямо перед временем, так что здесь начинается сложная часть. Я хочу получить только время и имена команд, как указано выше, из тех строк таблицы, где дата равна дате, когда я запускаю этот код.

Единственное, что мне пока удалось сделать, это немного, я могу только получить время и название команды, используя этот код:

import lxml.html
html = lxml.html.parse("http://gbgfotboll.se/information/?scr=table&ftid=51168")
test=html.xpath("//*[@id='content-primary']/table[3]/tbody/tr[1]/td[1]/span/span//text()")

print test

что дает мне результат ['2014-09-26', ' 19:30'] после этого я не понимаю, как перебирать разные строки таблицы, желая получить конкретные ячейки таблицы, где дата соответствует дате, когда я запускаю код.

Я надеюсь, что вы можете ответить столько, сколько сможете.


person Community    schedule 21.09.2014    source источник


Ответы (2)


Если я вас понял, попробуйте что-то вроде этого:

import lxml.html
url = "http://gbgfotboll.se/information/?scr=table&ftid=51168"
html = lxml.html.parse(url)
for i in range(12):
    xpath1 = ".//*[@id='content-primary']/table[3]/tbody/tr[%d]/td[1]/span/span//text()" %(i+1)
    xpath2 = ".//*[@id='content-primary']/table[3]/tbody/tr[%d]/td[2]/a/text()" %(i+1)
    print html.xpath(xpath1)[1], html.xpath(xpath2)[0]

Я знаю, что это хрупко, и есть лучшие решения, но это работает. ;)

Редактировать:
Лучше использовать BeautifulSoup:

from bs4 import BeautifulSoup
import requests

respond = requests.get("http://gbgfotboll.se/information/?scr=table&ftid=51168")
soup = BeautifulSoup(respond.text)
l = soup.find_all('table')
t = l[2].find_all('tr') #change this to [0] to parse first table
for i in t:
    try:
        print i.find('span').get_text()[-5:], i.find('a').get_text()
    except AttributeError:
        pass

Edit2: страница не отвечает, но это должно работать:

from bs4 import BeautifulSoup
import requests

respond = requests.get("http://gbgfotboll.se/information/?scr=table&ftid=51168")
soup = BeautifulSoup(respond.text)
l = soup.find_all('table')
t = l[2].find_all('tr')
time = ""
for i in t:
    try:
        dateTime = i.find('span').get_text()
        teamName = i.find('a').get_text()
        if time == dateTime[:-5]:
            print dateTime[-5,], teamName
        else:
            print dateTime, teamName
            time = dateTime[:-5]
    except AttributeError:
        pass

lxml:

import lxml.html
url = "http://gbgfotboll.se/information/?scr=table&ftid=51168"
html = lxml.html.parse(url)
dateTemp = ""
for i in range(12):
    xpath1 = ".//*[@id='content-primary']/table[3]/tbody/tr[%d]/td[1]/span/span//      text()" %(i+1)
    xpath2 = ".//*[@id='content-primary']/table[3]/tbody/tr[%d]/td[2]/a/text()" %(i+1)
    time = html.xpath(xpath1)[1]
    date = html.xpath(xpath1)[0]
    teamName = html.xpath(xpath2)[0]
    if date == dateTemp:
        print time, teamName
    else:
        print date, time, teamName
person CodeNinja    schedule 21.09.2014
comment
Почему первый пример хрупкий? Вы только что пропустили одну вещь, которая мне была нужна. Он должен печатать время и названия команд только в том случае, если дата совпадает. Пример: допустим, мы запустили код 2014-09-26, затем, когда мы перебираем таблицу в цикле for, он должен проверить, соответствует ли дата дате в каждой строке таблицы: ‹span class=matchTid›‹span› 26.09.2014 Тогда код будет печатать только: 19:30 Guldhedens IK - IF Warta и 13:00 Romelanda UF - IK Virgo Потому что дата, которую они имеют, совпадает с датой запуска 2014-09-26 @CodeNinja Если бы вы могли ввести это в первый пример - person ; 21.09.2014
comment
Я бы проголосовал, если бы мог, но там написано, что мне нужно 15 репутации, чтобы проголосовать. Мне очень жаль, но я надеюсь, что вы все равно поможете мне, если сможете. @CodeNinja - person ; 21.09.2014
comment
Вы забыли ответить, почему он хрупкий. Также я читал, что xpath и lxml - лучшее решение для анализа html-страниц. Не могли бы вы также реализовать решение даты для вашего первого примера, используя lxml? Спасибо @CodeNinja - person ; 21.09.2014
comment
Отредактировано. Я плохо знаю lxml ;) lxml содержит методы, с помощью которых вы можете добиться большего успеха... Хрупкий, потому что я использовал range(12), это отстойно ;p - person CodeNinja; 21.09.2014
comment
Ха-ха, да, это правда, но я думаю, что могу исправить. Я все еще не думаю, что вы действительно поняли, что я хотел сделать, но с тем кодом, который вы мне дали, я могу настроить его так, как я хочу. Я буду использовать время импорта, чтобы получить текущее время. В любом случае, я опубликую ответ, когда сайт заработает, и я протестировал код, и обязательно дам вам знать, когда я это сделаю. Спасибо за помощь! :D @CodeNinja - person ; 21.09.2014

Итак, благодаря помощи @CodeNinja, я немного подправил его, чтобы получить именно то, что хотел. Я импортировал время, чтобы получить дату запуска кода. В любом случае, вот код того, что я хотел. Спасибо вам за помощь!!

import lxml.html
import time
url = "http://gbgfotboll.se/information/?scr=table&ftid=51168"
html = lxml.html.parse(url)
currentDate = (time.strftime("%Y-%m-%d"))
for i in range(12):
    xpath1 = ".//*[@id='content-primary']/table[3]/tbody/tr[%d]/td[1]/span/span//text()" %(i+1)
    xpath2 = ".//*[@id='content-primary']/table[3]/tbody/tr[%d]/td[2]/a/text()" %(i+1)
    time = html.xpath(xpath1)[1]
    date = html.xpath(xpath1)[0]
    teamName = html.xpath(xpath2)[0]
    if date == currentDate:
        print time, teamName

Итак, вот ОКОНЧАТЕЛЬНАЯ версия того, как это сделать правильно. Это будет анализировать все строки таблицы, которые у него есть, без использования «диапазона» в цикле for. Я получил этот ответ из моего другого сообщения здесь: Перебрать все строки в таблице, используя python lxml xpath

import lxml.html
from lxml.etree import XPath
url = "http://gbgfotboll.se/information/?scr=table&ftid=51168"
date = '2014-09-27'

rows_xpath = XPath("//*[@id='content-primary']/table[3]/tbody/tr[td[1]/span/span//text()='%s']" % (date))
time_xpath = XPath("td[1]/span/span//text()[2]")
team_xpath = XPath("td[2]/a/text()")

html = lxml.html.parse(url)

for row in rows_xpath(html):
    time = time_xpath(row)[0].strip()
    team = team_xpath(row)[0]
    print time, team
person Community    schedule 22.09.2014