Contar caracteres de un archivo HTML con Python

Oct 13 2020

Acabo de completar el nivel 2 de The Python Challenge en pythonchallenge.com y estoy en el proceso de aprender Python, así que por favor tengan paciencia conmigo y con cualquier error tonto que pueda haber cometido.

Estoy buscando comentarios sobre lo que podría haber hecho mejor en mi código. Dos áreas en concreto:

  • ¿Cómo podría haber identificado más fácilmente la sección de comentarios del archivo HTML? Utilicé un método sencillo que encontró el final del comentario (o el comienzo técnicamente, pero cuenta desde el final) y me dio algunos caracteres adicionales que pude reconocer y anticipar (el extra "->" y "-"). ¿Qué condición hubiera encontrado mejor este comentario para poder ponerlo en una nueva cadena para ser contado?

Esto es lo que escribí:

from collections import Counter
import requests

page = requests.get('http://www.pythonchallenge.com/pc/def/ocr.html')

pagetext = ""
pagetext = (page.text)
#find out what number we are going back to

i = 1
x = 4
testchar = ""
testcharstring = ""


while x == 4:
    testcharstring = pagetext[-i:]
    testchar = testcharstring[0]
    if testchar == "-":
        testcharstring = pagetext[-(i+1)]
        testchar = testcharstring[0]
        if testchar == "-":
            testcharstring = pagetext[-(i+2)]
            testchar = testcharstring[0]
            if testchar == "!":
                testcharstring = pagetext[-(i+3)]
                testchar = testcharstring[0]
                if testchar == "<":
                    x = 3
            else:
                i += 1
                x = 4
        else:
            i += 1
            x = 4
    else:
        i += 1
print(i)

newstring = pagetext[-i:]

charcount = Counter(newstring)

print(charcount)

Y este es el código fuente HTML:

<html>
<head>
  <title>ocr</title>
  <link rel="stylesheet" type="text/css" href="../style.css">
</head>
<body>
<center><img src="ocr.jpg">
<br><font color="#c03000">
recognize the characters. maybe they are in the book, <br>but MAYBE they 
are in the page source.</center>

<br>
<br>
<br>

<font size="-1" color="gold">
General tips:
<li>Use the hints. They are helpful, most of the times.</li>
<li>Investigate the data given to you.</li>
<li>Avoid looking for spoilers.</li>
<br>
Forums: <a href="http://www.pythonchallenge.com/forums"/>Python Challenge Forums</a>, 
read before you post.
<br>
IRC: irc.freenode.net #pythonchallenge
<br><br>
To see the solutions to the previous level, replace pc with pcc, i.e. go 
to: http://www.pythonchallenge.com/pcc/def/ocr.html

</body>
</html>

<!--
find rare characters in the mess below:
-->

<!--

Seguido por miles de caracteres y el comentario concluye con '->'

Respuestas

2 fartgeek Oct 13 2020 at 20:36

No tengo suficiente reputación para comentar, así que debo decir esto en una respuesta. Parece complicado de usar

    while x == 4:

y luego haz

    x = 3

siempre que quieras salir del círculo. Parece mejor hacerlo

    while True:

y cuando quieras salir del círculo haz

    break

¡Salud!

1 AJNeufeld Oct 14 2020 at 05:51

Código redundante

pagetext = ""
pagetext = (page.text)

La primera línea asigna una cadena vacía a pagetext. La segunda línea ignora los contenidos que ya están en pagetexty asigna un valor diferente a la variable.

¿Por qué molestarse con la primera declaración? Simplemente hace que el código sea más largo, más lento y más difícil de entender.

¿Por qué molestarse con el (...)alrededor page.text? Tampoco sirven para ningún propósito.

Nombres de variables

Variables como ison un arma de doble filo. Lo está usando como un índice de bucle y luego lo está usando para hacer referencia a una ubicación encontrada después de que termina el bucle. Pero ipor sí solo no tiene mucho significado. posnpodría ser más claro. last_comment_posnsería mucho más claro, aunque muy detallado.

PEP-8 recomienda usar guiones bajos para separar palabras en nombres de variables: es decir, char_countno use, charcountetc.

Buscando una cadena de caracteres

Las cadenas de Python tienen funciones integradas para buscar una subcadena en una cadena más grande. Por ejemplo, str.findpodría encontrar rápidamente la primera aparición de <!--en el texto de la página.

i = pagetext.find("<!--")

Pero no estás buscando el primero; estás buscando el último. Pitón de nuevo tiene cubierto, con la función de búsqueda inversa: str.rfind.

i = pagetext.rfind("<!--")

Pero esto todavía encuentra el índice de la última aparición. Desea los caracteres después del marcador de comentario, por lo que debemos saltar hacia adelante 4 caracteres adicionales:

if i >= 0:
    newstring = pagetext[i+4:]

Código mejorado

import requests
from collections import Counter

page = requests.get('http://www.pythonchallenge.com/pc/def/ocr.html')
page.raise_for_status()  # Crash if the request didn't succeed
page_text = page.text

posn = page_text.rfind("<!--")
print(posn)

if posn >= 0:
    comment_text = page_text[posn+4:]    # Fix!  This is to end of string, not end of comment!
    char_count = Counter(comment_text)
    print(char_count)