Есть ли в скрипте Google Apps что-то вроде getElementById?

Я собираюсь использовать Google App Script для получения списка программ с сайта радиостанции. Как я могу выбрать указанные элементы на веб-странице, указав идентификатор элемента? Поэтому я могу получить программы на веб-странице.

3 ответа

Решение

Редактирование, декабрь 2013 г.: Google устарела Xml сервис, заменив его XmlService, Сценарий в этом ответе был обновлен для использования нового сервиса. Новому сервису требуются совместимые со стандартами XML и HTML, а старый отказывался от таких проблем, как отсутствие меток закрытия.


Взгляните на Учебник: Разбор XML-документа. (По состоянию на декабрь 2013 г. этот учебник по-прежнему доступен, хотя служба Xml устарела.) Начиная с этой основы, вы можете воспользоваться синтаксическим анализом XML в службах сценариев для навигации по странице. Вот небольшой скрипт, работающий на вашем примере:

function getProgrammeList() {
  txt = '<html> <body> <div> <div> <div id="here">hello world!!</div> </div> </div> </html>'

  // Put the receieved xml response into XMLdocument format
  var doc = Xml.parse(txt,true);

  Logger.log(doc.html.body.div.div.div.id +" = "
            +doc.html.body.div.div.div.Text );    /// here = hello world!!

  debugger;  // Pause in debugger - examine content of doc
}

Чтобы получить реальную страницу, начните с этого:

var url = 'http://blah.blah/whatever?querystring=foobar';
var txt = UrlFetchApp.fetch(url).getContentText();
....

Если вы посмотрите на документацию для getElements вы увидите, что есть поддержка для извлечения определенных тегов, например, "div". Это находит прямых потомков определенного элемента, но не исследует весь документ XML. Вы должны быть в состоянии написать функцию, которая пересекает документ, исследующий id каждого div элемент, пока он не найдет ваш список программ.

var programmeList = findDivById(doc,"here");

Редактировать - я не мог с собой поделать...

Вот полезная функция, которая сделает это.

/**
 * Find a <div> tag with the given id.
 * <pre>
 * Example: getDivById( html, 'tagVal' ) will find
 * 
 *          <div id="tagVal">
 * </pre>
 *
 * @param {Element|Document}
 *                     element     XML document or element to start search at.
 * @param {String}     id      HTML <div> id to find.
 *
 * @return {XmlElement}        First matching element (in doc order) or null.
 */
function getDivById( element, id ) {
  // Call utility function to do the work.
  return getElementByVal( element, 'div', 'id', id );
}

/**
 * !Now updated for XmlService!
 *
 * Traverse the given Xml Document or Element looking for a match.
 * Note: 'class' is stripped during parsing and cannot be used for
 * searching, I don't know why.
 * <pre>
 * Example: getElementByVal( body, 'input', 'value', 'Go' ); will find
 * 
 *          <input type="submit" name="btn" value="Go" id="btn" class="submit buttonGradient" />
 * </pre>
 *
 * @param {Element|Document}
 *                     element     XML document or element to start search at.
 * @param {String}     elementType XML element type, e.g. 'div' for <div>
 * @param {String}     attr        Attribute or Property to compare.
 * @param {String}     val         Search value to locate
 *
 * @return {Element}               First matching element (in doc order) or null.
 */
function getElementByVal( element, elementType, attr, val ) {
  // Get all descendants, in document order
  var descendants = element.getDescendants();
  for (var i =0; i < descendants.length; i++) {
    var elem = descendants[i];
    var type = elem.getType();
    // We'll only examine ELEMENTs
    if (type == XmlService.ContentTypes.ELEMENT) {
      var element = elem.asElement();
      var htmlTag = element.getName();
      if (htmlTag === elementType) {
        if (val === element.getAttribute(attr).getValue()) {
          return element;
        }
      }
    }
  }
  // No matches in document
  return null;
}

Применяя это к вашему примеру, мы получаем это:

function getProgrammeList() {
  txt = '<html> <body> <div> <div> <div id="here">hello world!!</div> </div> </div> </html>'

  // Get the receieved xml response into an XML document
  var doc = XmlService.parse(txt);

  var found = getDivById(doc.getElement(),'here');
  Logger.log(found.getAttribute(attr).getValue()  
             + " = "
             + found.getValue());    /// here = hello world!!
}

Примечание: см. Этот ответ для практического примера использования этих утилит.

Кто-то сделал пример здесь, где следующие пользовательские функции доступны для вырезания и вставки:

  • getElementById ()
  • getElementsByClassName ()
  • getElementsByTagName ()

Тогда вы можете сделать что-то вроде этого

function doGet() {
  var html = UrlFetchApp.fetch('http://en.wikipedia.org/wiki/Document_Object_Model').getContentText();
  var doc = XmlService.parse(html);
  var html = doc.getRootElement();
  var menu = getElementsByClassName(html, 'menu-classname')[0];
  return menu;
}

Я собираюсь предположить, что вы имеете в виду использование UrlFetchApp fetch() метод. В этом случае ответ - нет, в контексте того, о чем вы думаете.

Если вы посмотрите на тип возвращаемого значения для fetch() в документации он возвращает HTTPResponse. Для этого есть несколько методов, но большинство из них включают получение возвращаемых данных в виде строки. Хорошей новостью является то, что вы все равно можете использовать любой (ну, большинство) традиционных методов JS String, описанных здесь, - чтобы вы могли использовать search(), match()и т. д. В зависимости от вашего проекта вы можете использовать их для поиска нужных данных в ответе.

Другие вопросы по тегам