Я вчера написал об этом вопросе, но все предложили мне использовать библиотеку BeautifulSoup. Мне не разрешают использовать какие-либо внешние библиотеки для класса, но я продвинулся немного дальше. Код должен открывать данный веб-сайт и добавлять любую информацию между тегами заголовка. Это вводный класс, так что я понимаю, что могу спросить кое-что довольно простое. Как я могу исправить любые синтаксические ошибки? Особая проблема заключается в объявлении моей переменной "findHeader".

Редактировать: Traceback (последний вызов был последним): Файл "C: \ Users \ Cameron \ Desktop \ заголовок сайта search.py", строка 16, в if (findHeader, headerEnd) в строке: TypeError: 'in' требуется строка слева операнд, а не кортеж

from urllib.request import urlopen
address = "http://www.hobo-web.co.uk/headers/"
webPage = urlopen (address)

list = []

encoding = "utf-8"
for line in webPage:
    line = str(line, encoding)
    findHeader = ('h1', 'h2', 'h3', 'h4', 'h5', 'h6')
    headerEnd = ('/h1', '/h2', '/h3', '/h4', '/h5', '/h6')
    if (findHeader, headerEnd) in line:
        start = line.index(findHeader, headerEnd) + len(findHeader, headerEnd)
        last = line.index('"', start)
        list.append(line[start : last])

webPage.close()
1
Cameron 15 Дек 2015 в 17:35

4 ответа

Лучший ответ

Вот еще одно очень простое решение проблемы. Я считаю, что вы хотите найти подходящие заголовки (например, <h1> и </h1> в одной строке). Это очень простое решение, которое не использует какую-либо внешнюю библиотеку:

findHeader = ('<h1>', '<h2>', '<h3>', '<h4>', '<h5>', '<h6>')

line = 'This is the <h1>header content</h1> and this is not'
for startHeader in findHeader:
    endHeader = '</'+startHeader[1:]
    if (startHeader in line) and (endHeader in line):
        content = line.split(startHeader)[1].split(endHeader)[0]
        print content

Распечатывает:

header content

Чтобы вставить это в свой код:

from urllib.request import urlopen

address = "http://www.w3schools.com/html/html_head.asp"
webPage = urlopen (address)

encoding = "utf-8"

for line in webPage:
    findHeader = ('<h1>', '<h2>', '<h3>', '<h4>', '<h5>', '<h6>')
    line = str(line, encoding)

    for startHeader in findHeader:        
        endHeader = '</'+startHeader[1:]
        if (startHeader in line) and (endHeader in line):
            content = line.split(startHeader)[1].split(endHeader)[0]
            print (content)



webPage.close()  
0
toti08 15 Дек 2015 в 15:51

if (findHeader, headerEnd) in line: Как говорит трассировка, вы не можете проверить, находится ли кортеж в строке. Я предполагаю, что вы пытаетесь проверить, находятся ли они в очереди. Это работа для any.

if any(header in line for header in (findHeader, headerEnd)):
    do_things
0
Morgan Thrapp 15 Дек 2015 в 14:50

Как ваше сообщение об ошибке говорит:

Ошибка типа: для 'in' в качестве левого операнда требуется строка, а не кортеж

Когда вы говорите « ищите что-то в этой строке, », вы ожидаете, что вы ищете строку в этой строке. Если вы хотите проверить, содержит ли строка (line) хотя бы один из нескольких возможных вариантов (findHeader и / или headerEnd), вам следует выполнить некоторые действия. вид итерации, проверяющий каждую опцию, чтобы увидеть, присутствует ли она.

Существует множество способов справиться с подобной итерацией / проверкой в Python. Некоторые из них являются однострочными решениями, а некоторые занимают несколько строк. На мой взгляд, наиболее читаемый способ - написать цикл, который будет перебирать список возможностей (findHeader) и проверять наличие значений. Если присутствует одно из значений, выйдите из цикла и проверьте, присутствует ли соответствующий закрывающий тег (headerEnd).

Ниже приведен пересмотр вашего кода для выполнения такой проверки очень читабельным способом:

for line in webPage.split("\n"):
    line = str(line, encoding)
    findHeader = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
    headerEnd = ['/h1', '/h2', '/h3', '/h4', '/h5', '/h6']
    headerIndexNumber = -1
    for i in range(len(findHeader)):
        # Attempt to find the start of a header in the line
        if(( '<' + findHeader[i]) in line):
            # The line contains what appears to be the start of a header
            headerIndexNumber = i
            break
        # End if
    # End for

    # Check if the for loop above found a header index
    if(headerIndexNumber >= 0):
        # Great, we found a header index number in the line above
        # Now let's check for a respective closing tag.
        if(('<' + headerEnd[headerIndexNumber]) in line):
            # Cool, the line also appears to contain a closing tag for
            # the same type of header.

            ## ... <YOUR CODE HERE FOR DOING SOMETHING EITHER BETWEEN
            ## ...  OR WITH THE HTML HEADER TAGS> ...

        # End if(header closing tag was found in line)
    # End if(header start tag was found in line)
# End foreach loop (line in webPage)

Очевидно, это всего лишь пересмотренный кусок вашего кода. Если вы решите использовать это как свое решение, вам нужно будет поместить его в существующий код там, где это уместно, и вам все равно нужно будет написать внутреннюю логику (т. Е. Код, который обрабатывает то, что вы делаете однажды найден тег заголовка в строке).

Тем не менее, я попытался написать этот код очень читабельным и понятным способом с комментариями, которые объясняют, что делает каждая строка. Если какая-либо вещь в коде, который я включил выше, не имеет смысла, пожалуйста, оставьте комментарий, и я постараюсь объяснить это.

Несколько замечаний по предоставленному коду:

  • Я делаю for line in webPage.split("\n"). Я проверил это локально, установив webPage в строку, содержащую исходный HTML-код веб-страницы. Из-за этого источник веб-страницы нужно было разбить на отдельные строки, иначе цикл for просто будет проходить через каждый отдельный символ в HTML-коде веб-страницы, а не через полные строки. Если это не относится к вашему коду, просто удалите команду split.

  • Когда я проверяю теги заголовка в строке, я добавляю < к искомому значению. Это потому, что HTML-теги всегда начинаются с <. Так что это предотвратит ложно-положительное совпадение, если в строке только что написано «h1».

РЕДАКТИРОВАТЬ . Что касается вашего комментария, OP, ниже приведен простой способ распечатать строки между тегами h на основе кода, который вы опубликовали в Pastebin:

from urllib.request import urlopen
address = "http://www.w3schools.com/html/html_head.asp"
webPage = urlopen (address)

encoding = "utf-8"

list = []

for line in webPage:
    findHeader = ('<h1>', '<h2>', '<h3>', '<h4>', '<h5>', '<h6>')
    line = str(line, encoding)
    for startHeader in findHeader:        
        endHeader = '</'+startHeader[1:]
        if (startHeader in line) and (endHeader in line):
            content = line.split(startHeader)[1].split(endHeader)[0]
            list.append(line)


for h in list:
    print((h[4:]).strip()[:-5])

webPage.close()
0
Spencer D 18 Дек 2015 в 22:22

Если ваш случай так прост, я предлагаю использовать простое регулярное выражение.

import re

line = 'I am a <h1>jedi</h1> and you are not'
regex = re.compile('<h[0-9]>(.*)</h[0-9]>')
match = regex.search(line)
if match:
    print(match.group(1))

Он вернется

jedi

Просто для полноты, вы не можете найти кортеж в строке так же, как вы не можете найти список в строке. Если вам действительно нужно следовать этому подходу, вы должны проверить каждый элемент в списке на соответствие вашей строке.

0
Simone Zandara 15 Дек 2015 в 14:52