Senate source model

The source of camara-senadores-mex is not a formal public API. It is a combination of HTML routes and an AJAX view used by the institutional portal interface.

The source model is best understood as a set of anchors:

/66/
├── votacion/{id}
│   └── app/votaciones/functions/viewTableVot.php
└── senador/{id}

/66/: current site as operational container

The /66/ segment acts as the entry point of the current site. In practice, it allows access to both voting events and profiles under a common route convention.

It must not be read as a guarantee that all content belongs to the LXVI Legislature. The repository documents historical voting events from LX to LXVI that are accessible under that route. For that reason, the legislature of a voting event is parsed from the content when it exists and, when absent, inferred from the date.

Vote page

The base page for a voting event has this form:

https://www.senado.gob.mx/66/votacion/{id}

The HTML can contain temporal metadata, for example:

<strong>LXIII LEGISLATURA<br>TERCER AÑO DE EJERCICIO<br>SEGUNDO PERIODO ORDINARIO</strong>
<strong>Jueves 22 de febrero de 2018</strong>

The parser extracts:

FieldRule
legislatureRoman numeral in LEGISLATURA; if absent, inference from date.
yearOrdinal before AÑO DE EJERCICIO.
periodOrdinal before PERIODO, accepting both PERIODO and PERIODO ORDINARIO.
dateSpanish date converted to ISO format.

The vote HTML is not treated as the final source of roll-call votes. The current decision is to always query the associated AJAX endpoint.

AJAX endpoint for roll-call votes

The current endpoint for roll-call records is:

https://www.senado.gob.mx/66/app/votaciones/functions/viewTableVot.php

The current request is made as POST, not as a contractual GET:

method: POST
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Referer: https://www.senado.gob.mx/66/votacion/{id}
body: action=ajax&cell=1&order=DESC&votacion={id}&q=

The response is partial HTML with table rows. An expected pattern is:

<tr>
  <td class="text-center">1</td>
  <td><a href="/66/votaciones/577#info">Sen. González Canto, Félix Arturo</a></td>
  <td><a href="/66/votaciones/577#info">PRI</a></td>
  <td class="text-center">PRO</td>
</tr>

Conceptually, that row yields:

FieldSource
senador_idNumber extracted from the row href (/votaciones/{id}).
nombreName link text, after cleaning prefixes and Surname, Name order.
partidoThird-cell text.
votoFourth-cell text, joining text nodes when there are multiple fragments.

The AJAX response is primary evidence for roll-call votes, but not a guarantee of absolute completeness. If the source returns empty rows, incomplete metadata, or partial responses, those limits must remain visible in the database and in validation.

Senator page

Available profiles are queried with:

https://www.senado.gob.mx/66/senador/{id}

The spider considers a page valid when it finds the senator information section. From there it extracts observable fields:

FieldSelector / conceptual rule
nombreh2.nSenador, removing the Senador / Senadora prefix.
sexoInferred from the prefix when the site exposes it.
tipo_eleccionh3.tipoEleccion, normalized to observed values.
estadoh4.nEstadi.
urlVisited profile URL.

The /66/ portal does not guarantee a historical profile for every ID detected in votes. That absence is not corrected inside the extractor: available data is persisted and missing data is counted.

Trust model

The source is used conservatively:

  • /66/votacion/{id} provides context and temporal metadata.
  • viewTableVot.php provides roll-call rows through a form-urlencoded POST.
  • /66/senador/{id} provides profiles only when the page exists and contains a valid structure.
  • Incapsula/WAF introduces access variability; an absence may mean nonexistent data, an unpublished profile, a block, or an incomplete response.

Therefore, the project contract is not “everything the portal might know,” but “what the extractor can observe, parse, persist, and audit without inventing.”