Tutorial de jq para archivos HAR
Te voy a explicar cómo usar jq para trabajar con archivos .har. Un archivo HAR (HTTP Archive) es básicamente un JSON que guarda toda la interacción de red de un navegador, y jq es la herramienta perfecta para analizarlo desde la línea de comandos [citation:5][citation:8].
📚 Entendiendo la estructura de un archivo HAR
Antes de empezar, es útil conocer la estructura básica de un HAR. Todo el contenido está dentro de un objeto log que contiene una clave entries, que es un array con todas las peticiones [citation:8][citation:9]:
{
"log": {
"entries": [
{
"request": { ... },
"response": { ... },
"timings": { ... },
"startedDateTime": "...",
"time": ...
},
...
]
}
}
🔧 Instalación de jq
En Linux
# Debian/Ubuntu
sudo apt-get install jq
# CentOS/RHEL
sudo yum install jq
# O desde fuente
git clone https://github.com/stedolan/jq.git
cd jq
autoreconf -i
./configure
make
sudo make install
En macOS
brew install jq
En Windows
Puedes descargar el ejecutable desde la página oficial de jq [citation:3].
🚀 Operaciones básicas con jq en archivos HAR
1. Visualizar y validar el HAR
El filtro más simple es ., que muestra el JSON formateado y valida su estructura [citation:2][citation:4]:
cat archivo.har | jq '.'
2. Obtener todas las URLs de las peticiones
cat archivo.har | jq '.log.entries[].request.url'
Para obtenerlas sin comillas (formato raw):
cat archivo.har | jq -r '.log.entries[].request.url'
3. Ver métodos HTTP y URLs
cat archivo.har | jq '.log.entries[] | {method: .request.method, url: .request.url}'
🔍 Filtrado y selección avanzada
Filtrar por método HTTP
# Solo peticiones POST
cat archivo.har | jq '.log.entries[] | select(.request.method == "POST") | .request.url'
# Solo peticiones a una API específica
cat archivo.har | jq '.log.entries[] | select(.request.url | contains("/api/")) | .request.url'
Filtrar por código de respuesta
# Peticiones con error 404
cat archivo.har | jq '.log.entries[] | select(.response.status == 404) | {url: .request.url, status: .response.status}'
Filtrar por tipo de contenido
# Solo respuestas JSON
cat archivo.har | jq '.log.entries[] | select(.response.content.mimeType | contains("application/json")) | .request.url'
Filtrar usando expresiones regulares
# URLs que contengan un patrón específico
REQUEST_URI="facebook.com/api"
cat archivo.har | jq -r '.log.entries[] | select(.request.url | test("'$REQUEST_URI'")) | .request.url'
📊 Extracción de información específica
Extraer cabeceras HTTP específicas
Para obtener URLs junto con cabeceras específicas (Content-Type y Content-Encoding):
cat archivo.har | jq '.log.entries[] | {
url: .request.url,
content_type: (.response.headers[] | select(.name == "Content-Type") | .value // ""),
content_encoding: (.response.headers[] | select(.name == "Content-Encoding") | .value // "")
}'
Extraer tiempos de carga
cat archivo.har | jq '.log.entries[] | {
url: .request.url,
tiempo_total: .time,
espera: .timings.wait,
recepcion: .timings.receive
}'
Extraer contenido de respuestas JSON
# Extraer el cuerpo de respuestas JSON (útil para APIs)
cat archivo.har | jq -r '.log.entries[] | select(.response.content.mimeType | contains("json")) | .response.content.text | fromjson'
📈 Exportación a otros formatos
Convertir a CSV
Puedes generar un CSV con las columnas que necesites [citation:9]:
cat archivo.har | jq -r '["URL", "Status", "Content-Type"], (.log.entries[] | [
.request.url,
.response.status,
((.response.headers[] | select(.name == "Content-Type") | .value) // "")
]) | @csv' > salida.csv
Usando har2csv
Existe un script especializado llamado har2csv que simplifica esta tarea [citation:8]:
# Descargar el script
wget https://raw.githubusercontent.com/Nooshu/har2csv/main/har2csv.jq
chmod +x har2csv.jq
# Ejecutar
./har2csv.jq archivo.har > salida.csv
⚡ Técnicas avanzadas
Combinar múltiples archivos HAR
Si tienes varios archivos HAR y quieres combinarlos en uno solo [citation:3]:
jq -s '{
log: {
version: .[0].log.version,
creator: .[0].log.creator,
entries: (reduce .[] as $entry ([]; . + $entry.log.entries))
}
}' archivo1.har archivo2.har > combinado.har
Procesar archivos HAR muy grandes
Para archivos HAR enormes, usa el modo streaming para no cargar todo en memoria [citation:2][citation:7]:
jq --stream 'select(.[0][0] == "log" and .[0][1] == "entries") | .[1]' archivo_grande.har
Estadísticas básicas
# Número total de peticiones
cat archivo.har | jq '.log.entries | length'
# Peticiones por código de respuesta
cat archivo.har | jq '.log.entries | group_by(.response.status) | map({status: .[0].response.status, count: length})'
# Tiempo medio de respuesta
cat archivo.har | jq '[.log.entries[].time] | add / length'
💡 Consejos útiles
-
Siempre entre comillas simples: En Unix/Linux, usa
'filtro'para evitar que el shell interprete caracteres especiales [citation:2]. -
Formato raw con -r: Úsalo cuando quieras strings sin comillas, ideal para guardar en archivos [citation:2][citation:4].
-
Compacto con -c: Si prefieres cada objeto en una línea (útil para procesamiento posterior) [citation:2].
-
El operador //: Es muy útil para valores por defecto cuando una clave no existe:
.algoQuePodriaNoExistir // "valor_por_defecto"[citation:9].
¿Tienes algún objetivo específico con tu archivo HAR? Puedo ayudarte a construir el filtro exacto que necesitas.
Referencias
- 解析JSON并使用jq迭代对象 - 腾讯云开发者社区
- jq(1) — jq — Debian testing
- Parsing HAR-formatted audit log files
- jq notes
- Re: trying to parse lines from an awkwardly formatted HAR file ...
- Saint Louis University / Pius
- A jq program is a "filter": it takes an input, and produces an output\. There are a lot of builtin filters for extracting a particular field of an object, or converting a number to a string, or various other standard tasks\.
- GitHub - Nooshu/har2csv: Convert a har file to a CSV using jq
- 问解析HAR文件以获取HTTP头值表EN
- jq cheat sheet
Cuando tienes un campo como .log.entries[].response.content.text que contiene una cadena JSON (con caracteres escapados como \n), puedes convertirlo a un objeto JSON real usando la función fromjson de jq. Luego, si ese JSON es un array y quieres ver sus elementos individualmente (sin el contenedor), puedes usar .[] para iterar sobre él.
Extraer y mostrar elementos de un array JSON interno
jq '.log.entries[].response.content | select(.mimeType == "application/json") | .text | fromjson | .[]' archivo.har
Explicación:
.log.entries[].response.contentselecciona cada contenido de respuesta.select(.mimeType == "application/json")filtra solo los que son JSON..textobtiene la cadena JSON (con escapes).fromjsonla convierte en un objeto/array de jq..[]despliega cada elemento del array por separado (si el JSON es un array).
Si quieres ver los elementos con un formato más legible, puedes agregar -r para output raw (sin comillas) o -C para color.
Ver solo los elementos (sin claves adicionales)
Si el JSON interno es un array de objetos y solo quieres ver cada objeto, el comando anterior ya te dará cada objeto en una línea (o en formato pretty si usas jq sin -c). Si prefieres cada objeto en una línea compacta (para procesar con otras herramientas), añade -c:
jq -c '.log.entries[].response.content | select(.mimeType == "application/json") | .text | fromjson | .[]' archivo.har
Si el JSON interno no es un array sino un objeto
Si quieres ver solo las claves o valores del objeto, puedes hacer:
- Ver las claves:
fromjson | keys - Ver los valores:
fromjson | .[](si es un objeto,.[]devuelve sus valores) - Ver un campo específico:
fromjson | .campo
Manejo de posibles errores (texto no JSON o vacío)
jq '.log.entries[].response.content | select(.mimeType == "application/json") | .text | try fromjson catch "Error" | .[]?' archivo.har
El ? después de .[] suprime errores si el resultado no es un array.
Ejemplo concreto
Supón que en tu HAR tienes una respuesta JSON como:
{
"text": "[{\"id\":1,\"nombre\":\"Ejemplo\"},{\"id\":2,\"nombre\":\"Otro\"}]"
}
El comando:
jq '.log.entries[].response.content | select(.mimeType=="application/json") | .text | fromjson | .[]' archivo.har
producirá:
{
"id": 1,
"nombre": "Ejemplo"
}
{
"id": 2,
"nombre": "Otro"
}
¿Es esto lo que buscabas? Si necesitas extraer solo una parte específica de esos elementos o filtrarlos, puedo ayudarte a ajustar el filtro.