Пожалуйста, подготовьтесь к длительному чтению.Я нахожусь в тупике и не знаю, где искать ответ / что еще попробовать.Излишне говорить, что я немного новичок в программировании.За последние пару недель взломал этот проект.
ПРОБЛЕМА
Я получил эту таблицу, 25 строк, 2 столбца.Каждая строка имеет следующую структуру:
Необходимое событие
<td align=center>19/11/11<br>12:01:21 AM</td>
<td align=center><font color=#006633><a href=profiles.php?XID=1><font color=#006633>player1</font></a> hospitalized <a href=profiles.php?XID=2><font color=#006633>player2</font></a></font></td>
НЕ Необходимое событие CASE A
<td align="center">19/11/11<br />12:58:03 AM</td>
<td align="center"><font color="#AA0000">Someone hospitalized <a href=profiles.php?XID=1><font color="#AA0000">player1</font></a></font></td>
НЕ НЕОБХОДИМОЕ событие CASE B
<td align="center">19/11/11<br />12:58:03 AM</td>
<td align=center><font color=#006633><a href=profiles.php?XID=3><font color=#006633>player3</font></a> attacked <a href=profiles.php?XID=1><font color=#006633>player1</font></a> and lost </font></td>
Я использовал регулярное выражение для очистки необходимых данных.Моя проблема в том, что 2 списка не совпадают.Дата и время не всегда соответствуют точному событию.
1-я ПОПЫТКА при решении задачи
import mechanize
import re
htmlA1 = br.response().read()
patAttackDate = re.compile('<td align=center>(\d+/\d+/\d+)<br>(\d+:\d+:\d+ \w+)')
patAttackName = re.compile('<font color=#006633>(\w+)</font></a> hospitalized ')
searchAttackDate = re.findall(patAttackDate, htmlA1)
searchAttackName = re.findall(patAttackName, htmlA1)
pairs = zip(searchAttackDate, searchAttackName)
for i in pairs:
print (i)
Но это дает мне wrong time - correct event
тип списка.
например:
(('19/11/11', '9:47:51 PM'), 'user1') <- mismatch
(('19/11/11', '8:21:18 PM'), 'user1') <- mismatch
(('19/11/11', '7:33:00 PM'), 'user1') <- As a consequence of the below, the rest upwards are mismatched
(('19/11/11', '7:32:38 PM'), 'user2') <- NOT a match, case B
(('19/11/11', '7:32:22 PM'), 'user2') <- match ok
(('19/11/11', '7:26:53 PM'), 'user2') <- match ok
(('19/11/11', '7:25:24 PM'), 'user3') <- match ok
(('19/11/11', '7:24:22 PM'), 'user3') <- match ok
(('19/11/11', '7:23:25 PM'), 'user3') <- match ok
2-я ПОПЫТКА при решении проблемы
Так думал раздеть newline
со всей страницы и почистите таблицу, но:
import mechanize
import re
from BeautifulSoup import BeautifulSoup
htmlA1 = br.response().read()
stripped = htmlA1.replace(">\n<","><") #Removed all '\n' from code
soup = BeautifulSoup(stripped)
table = soup.find('table', width='90%')
table2 = table.findNext('table', width='90%')
table3 = table2.findNext('table', width='90%') #this is the table I need to work with
patAttackDate = re.compile('<td align="center">(\d+/\d+/\d+)<br />(\d+:\d+:\d+ \w+)')
searchAttackDate = re.findall(patAttackDate, table3)
print searchAttackDate
это дает мне ошибку:
return _compile(pattern, flags).findall(string)
TypeError: expected string or buffer
Что мне не хватает?
Бонусный вопрос:Есть ли способ объяснить, что XID является динамической переменной, но обойти его при использовании регулярного выражения / Beautifulsoup (или другой метод очистки)?По мере роста проекта мне может понадобиться включить часть кода XID, но я не хочу соответствовать ей.(не уверен, если это понятно)
Спасибо за ваше время
РЕДАКТИРОВАТЬ 1 : добавлен пример списка
РЕДАКТИРОВАТЬ 2 : Более четкое разделение кода
EDIT 3 : добавлен пример кода для данного решения, которое не работает
Test = '''<table><tr><td>date</td></tr></table>'''
soupTest = BeautifulSoup(Test)
test2 = soupTest.find('table')
patTest = re.compile('<td>(.*)</td>')
searchTest = patTest.findall(test2.getText())
print test2 # gives: <table><tr><td>date</td></tr></table>
print type(test2) # gives: <class 'BeautifulSoup.Tag'>
print searchTest #gives: []
EDIT 4 - Solution
import re
import mechanize
from BeautifulSoup import BeautifulSoup
htmlA1 = br.response().read()
stripped = htmlA1.replace(">\n<","><") #stripped '\n' from html
soup = BeautifulSoup(stripped)
table = soup.find('table', width='90%')
table2 = table.findNext('table', width='90%')
table3 = table2.findNext('table', width='90%') #table I need to work with
print type(table3) # gives <class 'BeautifulSoup.Tag'>
strTable3 = str(table3) #convert table3 to string type so i can regex it
patFinal = re.compile(('(\d+/\d+/\d+)<br />(\d+:\d+:\d+ \w+)</td><td align="center">'
'<font color="#006633"><a href="profiles.php\?XID=(\d+)">'
'<font color="#006633">(\w+)</font></a> hospitalized <a'), re.IGNORECASE)
searchFinal = re.findall(patFinal, strTable3)
for i in searchFinal:
print (i)
Пример вывода
('19/11/11', '1:08:07 AM', 'ID_user1', 'user1')
('19/11/11', '1:06:55 AM', 'ID_user1', 'user1')
('19/11/11', '1:05:46 AM', 'ID_user1', 'user1')
('19/11/11', '1:04:33 AM', 'ID_user1', 'user1')
('19/11/11', '1:03:32 AM', 'ID_user1', 'user1')
('19/11/11', '1:02:37 AM', 'ID_user1', 'user1')
('19/11/11', '1:00:43 AM', 'ID_user1', 'user1')
('19/11/11', '12:55:35 AM', 'ID_user2', 'user2')
EDIT 5 - намного более простое решение (с 1-й попытки - без Beautifulsoup)
import re
reAttack = (r'<td\s+align=center>(\d+/\d+/\d+)<br>(\d+:\d+:\d+\s+\w+)</td>\s*'
'<td.*?' #accounts for the '\n'
'<font\s+color=#006633>(\w+)</font></a>\s+hospitalized\s+')
for m in re.finditer(reAttack, htmlA1):
print 'date: %s; time: %s; player: %s' % (m.group(1), m.group(2), m.group(3))
Пример вывода
date: 19/11/11; time: 1:08:07 AM; player: user1
date: 19/11/11; time: 1:06:55 AM; player: user1
date: 19/11/11; time: 1:05:46 AM; player: user1
date: 19/11/11; time: 1:04:33 AM; player: user1
date: 19/11/11; time: 1:03:32 AM; player: user1
date: 19/11/11; time: 1:02:37 AM; player: user1
date: 19/11/11; time: 1:00:43 AM; player: user1
date: 19/11/11; time: 12:55:35 AM; player: user2