[ad_1]
Los datos de rastreo de motores de búsqueda que se encuentran dentro de los archivos de registro son una fuente fantástica de información para cualquier profesional de SEO.
Por analizar archivos de registro, puede comprender exactamente cómo los motores de búsqueda están rastreando e interpretando su sitio web, claridad que simplemente no puede obtener cuando confía en herramientas de terceros.
Esto le permitirá:
- Valide sus teorías proporcionando evidencia indiscutible de cómo se están comportando los motores de búsqueda.
- Priorice sus hallazgos ayudándole a comprender la escala de un problema y el posible impacto de solucionarlo.
- Descubra problemas adicionales que no son visibles cuando utiliza otras fuentes de datos.
Pero a pesar de la multitud de beneficios, los datos de los archivos de registro no se utilizan con tanta frecuencia como deberían. Las razones son comprensibles:
- Acceder a los datos generalmente implica pasar por un equipo de desarrollo, lo que puede llevar tiempo.
- Los archivos sin procesar pueden ser enormes y se proporcionan en un formato poco amigable, por lo que el análisis de los datos requiere esfuerzo.
- Es posible que las herramientas diseñadas para facilitar el proceso deban integrarse antes de que los datos puedan ser canalizados, y el costos puede ser prohibitivo.
Anuncio publicitario
Continuar leyendo a continuación
Todos estos problemas son barreras de entrada perfectamente válidas, pero no tienen por qué ser insuperables.
Con un poco de conocimiento básico de codificación, puede automatizar todo el proceso. Eso es exactamente lo que haremos en esta lección paso a paso sobre el uso Pitón para analizar los registros del servidor para SEO.
También encontrará un guión para comenzar.
Contenidos
Consideraciones iniciales
Uno de los mayores desafíos al analizar los datos de los archivos de registro es la gran cantidad de formatos potenciales. apache, Nginx, y IIS ofrecen una variedad de opciones diferentes y permiten a los usuarios personalizar los puntos de datos devueltos.
Para complicar aún más las cosas, muchos sitios web ahora usan CDN proveedores como Cloudflare, Cloudfront y Akamai para ofrecer contenido desde la ubicación de borde más cercana a un usuario. Cada uno de estos también tiene sus propios formatos.
Nos centraremos en el Formato de registro combinado para esta publicación, ya que este es el valor predeterminado para Nginx y una opción común en los servidores Apache.
Anuncio publicitario
Continuar leyendo a continuación
Si no está seguro del tipo de formato con el que está tratando, servicios como Builtwith y Wappalyzer brindan información excelente sobre la pila tecnológica de un sitio web. Pueden ayudarlo a determinar esto si no tiene acceso directo a un interesado técnico.
¿Aún no sabes nada? Intente abrir uno de los archivos sin formato.
A menudo, los comentarios se proporcionan con información sobre los campos específicos, que luego pueden ser referenciados.
#Fields: time c-ip cs-method cs-uri-stem sc-status cs-version 17:42:15 172.16.255.255 GET /default.htm 200 HTTP/1.0
Otra consideración es qué motores de búsqueda queremos incluir, ya que esto deberá tenerse en cuenta en nuestro filtrado y validación inicial.
Para simplificar las cosas, nos centraremos en Google, dado su dominante 88% Cuota de mercado estadounidense.
Empecemos.
1. Identificar archivos y determinar formatos
Para realizar un análisis SEO significativo, queremos un mínimo de ~ 100k solicitudes y datos de 2 a 4 semanas para el sitio promedio.
Debido al tamaño de los archivos involucrados, los registros generalmente se dividen en días individuales. Está prácticamente garantizado que recibirá varios archivos para procesar.
Como no sabemos con cuántos archivos trataremos a menos que los combinemos antes de ejecutar el script, un primer paso importante es generar una lista de todos los archivos en nuestra carpeta usando el globo módulo.
Esto nos permite devolver cualquier archivo que coincida con un patrón que especifiquemos. Como ejemplo, el siguiente código coincidiría con cualquier archivo TXT.
import glob files = glob.glob('*.txt')
Los archivos de registro se pueden proporcionar en una variedad de formatos de archivo, sin embargo, no solo TXT.
De hecho, en ocasiones, es posible que la extensión del archivo no sea una que usted reconozca. Aquí hay un archivo de registro sin procesar del servicio de entrega de registros de Akamai, que lo ilustra perfectamente:
bot_log_100011.esw3c_waf_S.202160250000-2000-41
Además, es posible que los archivos recibidos se dividan en varias subcarpetas y no queremos perder el tiempo copiándolos en una ubicación única.
Afortunadamente, glob admite tanto búsquedas recursivas como operadores comodín. Esto significa que podemos generar una lista de todos los archivos dentro de una subcarpeta o subcarpetas secundarias.
Anuncio publicitario
Continuar leyendo a continuación
files = glob.glob('**/*.*', recursive=True)
A continuación, queremos identificar qué tipos de archivos están dentro de nuestra lista. Para hacer esto, el Tipo de Mimica del archivo específico se puede detectar. Esto nos dirá exactamente con qué tipo de archivo estamos tratando, independientemente de la extensión.
Esto se puede lograr usando python-magic, un envoltorio alrededor de la biblioteca libmagic C y creando una función simple.
pip install python-magic pip install libmagic
import magic def file_type(file_path): mime = magic.from_file(file_path, mime=True) return mime
Comprensión de listas Luego se puede usar para recorrer nuestros archivos y aplicar la función, creando un diccionario para almacenar tanto los nombres como los tipos.
file_types = [file_type(file) for file in files] file_dict = dict(zip(files, file_types))
Finalmente, una función y una mientras que bucle para extraer una lista de archivos que devuelven un tipo MIME de texto / plano y excluir cualquier otra cosa.
uncompressed = [] def file_identifier(file): for key, value in file_dict.items(): if file in value: uncompressed.append(key) while file_identifier('text/plain'): file_identifier('text/plain') in file_dict
2. Extraiga las solicitudes del motor de búsqueda
Después de filtrar los archivos en nuestra (s) carpeta (s), el siguiente paso es filtrar los archivos en sí mismos extrayendo solo las solicitudes que nos interesan.
Anuncio publicitario
Continuar leyendo a continuación
Esto elimina la necesidad de combinar los archivos utilizando utilidades de línea de comandos como GREP o FINDSTR, ahorrando una búsqueda inevitable de 5 a 10 minutos a través de las pestañas y marcadores abiertos del cuaderno para encontrar el comando correcto.
En este caso, como solo queremos solicitudes de Googlebot, la búsqueda de “Googlebot” coincidirá con todas las agentes de usuario relevantes.
Podemos usar la función abierta de Python para leer y escribir nuestro archivo y el módulo de expresiones regulares de Python, RE, para realizar la búsqueda.
import re pattern = 'Googlebot' new_file = open('./googlebot.txt', 'w', encoding='utf8') for txt_files in uncompressed: with open(txt_files, 'r', encoding='utf8') as text_file: for line in text_file: if re.search(pattern, line): new_file.write(line)
Regex hace que esto sea fácilmente escalable mediante un operador OR.
pattern = 'Googlebot|bingbot'
3. Solicitudes de análisis
en un Publicación anterior, Hamlet Batista brindó orientación sobre cómo usar expresiones regulares para analizar solicitudes.
Como enfoque alternativo, usaremos Pandas‘potente analizador CSV incorporado y algunas funciones básicas de procesamiento de datos para:
- Elimina las columnas innecesarias.
- Formatee la marca de tiempo.
- Cree una columna con URL completas.
- Cambie el nombre y reordene las columnas restantes.
En lugar de codificar un nombre de dominio, el aporte La función se puede utilizar para solicitar al usuario y guardar esto como una variable.
Anuncio publicitario
Continuar leyendo a continuación
whole_url = input('Please enter full domain with protocol: ') # get domain from user input df = pd.read_csv('./googlebot.txt', sep='s+', error_bad_lines=False, header=None, low_memory=False) # import logs df.drop([1, 2, 4], axis=1, inplace=True) # drop unwanted columns/characters df[3] = df[3].str.replace('[', '') # split time stamp into two df[['Date', 'Time']] = df[3].str.split(':', 1, expand=True) df[['Request Type', 'URI', 'Protocol']] = df[5].str.split(' ', 2, expand=True) # split uri request into columns df.drop([3, 5], axis=1, inplace=True) df.rename(columns = {0:'IP', 6:'Status Code', 7:'Bytes', 8:'Referrer URL', 9:'User Agent'}, inplace=True) #rename columns df['Full URL'] = whole_url + df['URI'] # concatenate domain name df['Date'] = pd.to_datetime(df['Date']) # declare data types df[['Status Code', 'Bytes']] = df[['Status Code', 'Bytes']].apply(pd.to_numeric) df = df[['Date', 'Time', 'Request Type', 'Full URL', 'URI', 'Status Code', 'Protocol', 'Referrer URL', 'Bytes', 'User Agent', 'IP']] # reorder columns
4. Validar solicitudes
Es increíblemente fácil suplantar a los agentes de usuario del motor de búsqueda, lo que hace que la validación de solicitudes sea una parte vital del proceso, para que no terminemos sacando conclusiones falsas al analizar nuestros propios rastreos de terceros.
Para hacer esto, instalaremos una biblioteca llamada dnspython y realizar un DNS inverso.
Pandas se puede usar para eliminar IP duplicadas y ejecutar las búsquedas en este DataFrame más pequeño, antes de volver a aplicar los resultados y filtrar las solicitudes no válidas.
Anuncio publicitario
Continuar leyendo a continuación
from dns import resolver, reversename def reverseDns(ip): try: return str(resolver.query(reversename.from_address(ip), 'PTR')[0]) except: return 'N/A' logs_filtered = df.drop_duplicates(['IP']).copy() # create DF with dupliate ips filtered for check logs_filtered['DNS'] = logs_filtered['IP'].apply(reverseDns) # create DNS column with the reverse IP DNS result logs_filtered = df.merge(logs_filtered[['IP', 'DNS']], how='left', on=['IP']) # merge DNS column to full logs matching IP logs_filtered = logs_filtered[logs_filtered['DNS'].str.contains('googlebot.com')] # filter to verified Googlebot logs_filtered.drop(['IP', 'DNS'], axis=1, inplace=True) # drop dns/ip columns
Adoptar este enfoque acelerará drásticamente las búsquedas, validando millones de solicitudes en minutos.
En el siguiente ejemplo, se procesaron ~ 4 millones de filas de solicitudes en 26 segundos.
5. Girar los datos
Después de la validación, nos quedamos con un conjunto de datos limpios y bien formateados y podemos comenzar a pivotar estos datos para analizar más fácilmente los puntos de interés de datos.
En primer lugar, comencemos con una agregación simple usando Pandas ‘ agrupar por y agg funciones para realizar un recuento del número de solicitudes para diferentes códigos de estado.
Anuncio publicitario
Continuar leyendo a continuación
status_code = logs_filtered.groupby('Status Code').agg('size')
Para replicar el tipo de recuento al que está acostumbrado en Excel, vale la pena señalar que necesitamos especificar una función agregada de ‘tamaño’, no de ‘recuento’.
El uso de count invocará la función en todos las columnas dentro del DataFrame y los valores nulos se manejan de manera diferente.
Restablecer el índice restaurará los encabezados de ambas columnas, y la última columna puede cambiarse de nombre a algo más significativo.
status_code = logs_filtered.groupby('Status Code').agg('size').sort_values(ascending=False).reset_index() status_code.rename(columns={0:'# Requests'}, inplace=True)
Para una manipulación de datos más avanzada, Pandas incorporado tablas dinamicas ofrecen una funcionalidad comparable a Excel, lo que hace posibles agregaciones complejas con una única línea de código.
En su nivel más básico, la función requiere un DataFrame e índice especificados, o índices si se requiere un índice múltiple, y devuelve los valores correspondientes.
Anuncio publicitario
Continuar leyendo a continuación
pd.pivot_table(logs_filtered, index['Full URL'])
Para mayor especificidad, se pueden declarar los valores requeridos y aplicar agregaciones (suma, media, etc.) utilizando el parámetro aggfunc.
También vale la pena mencionar el parámetro de columnas, que nos permite mostrar valores horizontalmente para una salida más clara.
status_code_url = pd.pivot_table(logs_filtered, index=['Full URL'], columns=['Status Code'], aggfunc="size", fill_value=0)
Aquí hay un ejemplo un poco más complejo, que proporciona un recuento de las URL únicas rastreadas por agente de usuario por día, en lugar de solo un recuento del número de solicitudes.
user_agent_url = pd.pivot_table(logs_filtered, index=['User Agent'], values=['Full URL'], columns=['Date'], aggfunc=pd.Series.nunique, fill_value=0)
Si todavía tiene problemas con la sintaxis, consulte Mito. Le permite interactuar con una interfaz visual dentro de Jupyter cuando usa JupyterLab, pero aún genera el código relevante.
Anuncio publicitario
Continuar leyendo a continuación
Incorporación de rangos
Para puntos de datos como bytes que probablemente tengan muchos valores numéricos diferentes, tiene sentido agrupar los datos.
Para hacerlo, podemos definir nuestros intervalos dentro de una lista y luego usar el recorte función para ordenar los valores en bins, especificando np.inf para capturar cualquier cosa por encima del valor máximo declarado.
byte_range = [0, 50000, 100000, 200000, 500000, 1000000, np.inf] bytes_grouped_ranges = (logs_filtered.groupby(pd.cut(logs_filtered['Bytes'], bins=byte_range, precision=0)) .agg('size') .reset_index() ) bytes_grouped_ranges.rename(columns={0: '# Requests'}, inplace=True)
La notación de intervalo se utiliza dentro de la salida para definir rangos exactos, p. Ej.
(50000 100000]
Los corchetes indican cuando un número es no incluido y un corchete cuando está incluido. Entonces, en el ejemplo anterior, el depósito contiene puntos de datos con un valor entre 50.001 y 100.000.
6. Exportar
El paso final de nuestro proceso es exportar nuestros datos de registro y pivotes.
Para facilitar el análisis, tiene sentido exportar esto a un archivo de Excel (XLSX) en lugar de un CSV. Los archivos XLSX admiten varias hojas, lo que significa que todos los DataFrames se pueden combinar en el mismo archivo.
Esto se puede lograr usando para sobresalir. En este caso, un Objeto ExcelWriter también debe especificarse porque se agrega más de una hoja al mismo libro de trabajo.
Anuncio publicitario
Continuar leyendo a continuación
writer = pd.ExcelWriter('logs_export.xlsx', engine="xlsxwriter", datetime_format="dd/mm/yyyy", options={'strings_to_urls': False}) logs_filtered.to_excel(writer, sheet_name="Master", index=False) pivot1.to_excel(writer, sheet_name="My pivot") writer.save()
Al exportar una gran cantidad de pivotes, ayuda a simplificar las cosas almacenando DataFrames y nombres de hojas en un diccionario y usando un bucle for.
sheet_names = { 'Request Status Codes Per Day': status_code_date, 'URL Status Codes': status_code_url, 'User Agent Requests Per Day': user_agent_date, 'User Agent Requests Unique URLs': user_agent_url, } for sheet, name in sheet_names.items(): name.to_excel(writer, sheet_name=sheet)
Una última complicación es que Excel tiene un límite de filas de 1.048.576. Estamos exportando todas las solicitudes, por lo que esto podría causar problemas al tratar con muestras grandes.
Debido a que los archivos CSV no tienen límite, se puede emplear una instrucción if para agregar una exportación CSV como respaldo.
Si la longitud del DataFrame del archivo de registro es mayor que 1.048.576, se exportará como un CSV, evitando que el script falle mientras se combinan los pivotes en una exportación singular.
if len(logs_filtered) <= 1048576: logs_filtered.to_excel(writer, sheet_name="Master", index=False) else: logs_filtered.to_csv('./logs_export.csv', index=False)
Pensamientos finales
Vale la pena invertir algo de tiempo en los conocimientos adicionales que se pueden obtener de los datos del archivo de registro.
Si ha estado evitando aprovechar estos datos debido a las complejidades involucradas, espero que esta publicación lo convenza de que estos se pueden superar.
Para aquellos que ya tienen acceso a las herramientas que están interesados en la codificación, espero que analizar este proceso de un extremo a otro les haya brindado una mayor comprensión de las consideraciones involucradas al crear un script más grande para automatizar tareas repetitivas que requieren mucho tiempo.
Anuncio publicitario
Continuar leyendo a continuación
El guión completo Lo que he creado se puede encontrar aquí en Github.
Esto incluye extras adicionales como la integración de la API de GSC, más pivotes y compatibilidad con dos formatos de registro más: Amazon ELB y W3C (utilizado por IIS).
Para agregar en otro formato, incluya el nombre dentro de la lista log_fomats en la línea 17 y agregue una declaración elif adicional en la línea 193 (o edite una de las existentes).
Por supuesto, existe un margen enorme para ampliar esto aún más. Esté atento a la publicación de la segunda parte que cubrirá la incorporación de datos de rastreadores de terceros, pivotes más avanzadosy visualización de datos.
Anuncio publicitario
Continuar leyendo a continuación
Más recursos:
Créditos de imagen
Todas las capturas de pantalla fueron tomadas por el autor, julio de 2021
[ad_2]
Source link