问题 有没有办法让YQL返回HTML?


我试图使用YQL从一系列网页中提取HTML的一部分。页面本身的结构略有不同(因此Yahoo Pipes“Fetch Page”及其“剪切内容”功能效果不佳)但我感兴趣的片段总是有相同的 class 属性。

如果我有这样的HTML页面:

<html>
  <body>
    <div class="foo">
      <p>Wolf</p>
      <ul>
        <li>Dog</li>
        <li>Cat</li>
      </ul>
    </div>
  </body>
</html>

并使用这样的YQL表达式:

SELECT * FROM html 
WHERE url="http://example.com/containing-the-fragment-above" 
AND xpath="//div[@class='foo']"

我得到的是(显然是无序的?)DOM元素,我想要的是HTML内容本身。我试过了 SELECT content 同样,但只选择文本内容。我想要HTML。这可能吗?


12827
2018-04-02 16:35


起源



答案:


你可以写一点 打开数据表 发出正常的YQL html 表查询和 字符串化 结果。类似于以下内容:

<?xml version="1.0" encoding="UTF-8" ?>
<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
  <meta>
    <sampleQuery>select * from {table} where url="http://finance.yahoo.com/q?s=yhoo" and xpath='//div[@id="yfi_headlines"]/div[2]/ul/li/a'</sampleQuery>
    <description>Retrieve HTML document fragments</description>
    <author>Peter Cowburn</author>
  </meta>
  <bindings>
    <select itemPath="result.html" produces="JSON">
      <inputs>
        <key id="url" type="xs:string" paramType="variable" required="true"/>
        <key id="xpath" type="xs:string" paramType="variable" required="true"/>
      </inputs>
      <execute><![CDATA[
var results = y.query("select * from html where url=@url and xpath=@xpath", {url:url, xpath:xpath}).results.*;
var html_strings = [];
for each (var item in results) html_strings.push(item.toXMLString());
response.object = {html: html_strings};
]]></execute>
    </select>
  </bindings>
</table>

然后,您可以使用YQL查询查询该自定义表,如:

use "http://url.to/your/datatable.xml" as html.tostring;
select * from html.tostring where 
  url="http://finance.yahoo.com/q?s=yhoo" 
  and xpath='//div[@id="yfi_headlines"]/div[2]/ul/li'

编辑: 刚刚意识到这是一个非常古老的问题,而且被撞了;至少答案在这里,最终,对于任何绊倒这个问题的人来说。 :)


8
2018-05-04 21:48



美丽!谢谢。我现在唯一的问题是如何将Yahoo Pipes变量放入YQL表达式中。例如,从html.tostring中选择*,其中url = item.link和xpath ='// div [@ id =“foo”]'给出错误“无效的identfier item.link。我是这里唯一支持的标识符语境“。我有什么想法吗? (抱歉,对于butchered代码段,看起来评论不允许格式化方式) - Joe Shaw
找出答案:创建一个单独的管道,它接受一个URL输入,将其插入到构建YQL查询的字符串构建器中,并将其作为查询附加到YQL窗口小部件。然后在主管道中,使用此新管道并将URL作为输入传入。我想我可能会特意为此开一个新问题,所以人们不必在这个评论中追捕它。 - Joe Shaw
开业时间: stackoverflow.com/questions/2889406/... - Joe Shaw
有点晚了,但是如果你想要一个更“官方”的解决方案,可以从datatables.org获得类似的东西: datatables.org/data/htmlstring.xml - esm
@hippietrail架构允许并且当前可以使用的内容并不总是匹配。 :) - salathe


答案:


你可以写一点 打开数据表 发出正常的YQL html 表查询和 字符串化 结果。类似于以下内容:

<?xml version="1.0" encoding="UTF-8" ?>
<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
  <meta>
    <sampleQuery>select * from {table} where url="http://finance.yahoo.com/q?s=yhoo" and xpath='//div[@id="yfi_headlines"]/div[2]/ul/li/a'</sampleQuery>
    <description>Retrieve HTML document fragments</description>
    <author>Peter Cowburn</author>
  </meta>
  <bindings>
    <select itemPath="result.html" produces="JSON">
      <inputs>
        <key id="url" type="xs:string" paramType="variable" required="true"/>
        <key id="xpath" type="xs:string" paramType="variable" required="true"/>
      </inputs>
      <execute><![CDATA[
var results = y.query("select * from html where url=@url and xpath=@xpath", {url:url, xpath:xpath}).results.*;
var html_strings = [];
for each (var item in results) html_strings.push(item.toXMLString());
response.object = {html: html_strings};
]]></execute>
    </select>
  </bindings>
</table>

然后,您可以使用YQL查询查询该自定义表,如:

use "http://url.to/your/datatable.xml" as html.tostring;
select * from html.tostring where 
  url="http://finance.yahoo.com/q?s=yhoo" 
  and xpath='//div[@id="yfi_headlines"]/div[2]/ul/li'

编辑: 刚刚意识到这是一个非常古老的问题,而且被撞了;至少答案在这里,最终,对于任何绊倒这个问题的人来说。 :)


8
2018-05-04 21:48



美丽!谢谢。我现在唯一的问题是如何将Yahoo Pipes变量放入YQL表达式中。例如,从html.tostring中选择*,其中url = item.link和xpath ='// div [@ id =“foo”]'给出错误“无效的identfier item.link。我是这里唯一支持的标识符语境“。我有什么想法吗? (抱歉,对于butchered代码段,看起来评论不允许格式化方式) - Joe Shaw
找出答案:创建一个单独的管道,它接受一个URL输入,将其插入到构建YQL查询的字符串构建器中,并将其作为查询附加到YQL窗口小部件。然后在主管道中,使用此新管道并将URL作为输入传入。我想我可能会特意为此开一个新问题,所以人们不必在这个评论中追捕它。 - Joe Shaw
开业时间: stackoverflow.com/questions/2889406/... - Joe Shaw
有点晚了,但是如果你想要一个更“官方”的解决方案,可以从datatables.org获得类似的东西: datatables.org/data/htmlstring.xml - esm
@hippietrail架构允许并且当前可以使用的内容并不总是匹配。 :) - salathe


我有同样的问题。我唯一能解决的问题是避免使用YQL,只使用正则表达式来匹配开始和结束标记:/。不是最好的解决方案,但如果html相对不变,那么模式就是说 <div class='name'> 至 <div class='just_after>`,然后你就可以逃脱。然后你可以得到之间的HTML。


2
2018-05-04 20:40



是的,这也是我最终做的事情。遗憾的是,页面的结构会根据输入的类型而改变,因此我最终需要多次拆分Feed以处理所有不同的类型并将它们合并/排序。一个真正的痛苦,但它的工作原理。 - Joe Shaw


YQL将页面转换为XML,然后对其执行XPath,然后获取DOMNodeList并将其序列化为输出的XML(如果需要,则转换为JSON)。您无法访问原始数据。

为什么不能处理XML而不是HTML?


0
2018-04-04 01:50



我在Yahoo Pipes的上下文中使用它,所以我想将HTML插入到RSS提要中,以便由提要阅读器/浏览器呈现。插入XML可能有效,但Pipes YQL模块似乎只是将DOM元素插入到文档中;我也没有看到获取XML源的方法。 - Joe Shaw