【问题标题】:Does JSSoup support select() similar to Beautiful Soup or JSoup?JSSoup 是否支持类似于 Beautiful Soup 或 JSoup 的 select()?
【发布时间】:2020-12-29 11:30:31
【问题描述】:

JSSoup(它本身声明“JavaScript + BeautifulSoup = JSSoup”)是否支持类似于Beautiful SoupJSoupselect() 操作来基于CSS 选择器选择元素?

我没找到,它可能以不同的名字存在吗?

【问题讨论】:

  • 也许,既然你使用的是原生js,你可以使用querySelectorquerySelectorAll
  • @Mr.Polywhirl 我有一个字符串,其中包含我要分析的 HTML,而不是页面的 DOM 本身。
  • 注意: Naming Style:JSSoup 尝试使用与 BeautifulSoup 相同的接口,因此 BeautifulSoup 用户可以无缝地使用 JSSoup。但是,JSSoup 使用 Javascript 的驼峰命名方式,而不是 Python 的下划线命名方式。比如BeautifulSoup中的find_all()被替换为findAll()
  • 现在 JSSoup 支持 CSS 选择器的 select()。

标签: javascript html web-scraping beautifulsoup jssoup


【解决方案1】:

您将无法使用类似于querySelectorquerySelectorAll 的选择器查询。

这是 JSsoup 中的findAll 定义:

{
  key: 'findAll',
  value: function findAll() {
    var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
    var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
    var string = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
    // ...
    var strainer = new SoupStrainer(name, attrs, string);
    // ...
  }
}

这里是SoupStrainer 构造函数:

function SoupStrainer(name, attrs, string) {
  _classCallCheck(this, SoupStrainer);

  if (typeof attrs == 'string') {
    attrs = { class: [attrs] };
  } else if (Array.isArray(attrs)) {
    attrs = { class: attrs };
  } else if (attrs && attrs.class && typeof attrs.class == 'string') {
    attrs.class = [attrs.class];
  }
  if (attrs && attrs.class) {
    for (var i = 0; i < attrs.class.length; ++i) {
      attrs.class[i] = attrs.class[i].trim();
    }
  }
  this.name = name;
  this.attrs = attrs;
  this.string = string;
  }

您需要将标签名称作为第一个参数传递,然后是属性。字符串被视为类名。

示例用法

const JSSoup = require('jssoup').default;

const html = `
<html>
  <head>
    <title>Hello World</title>
  </head>
  <body>
    <h1>Hello World</h1>
    <p class="foo">First</p>
    <p class="foo bar">Second</p>
    <div class="foo">Third</div>
  </body>
</html>
`;

const printTags = (tags) => console.log(tags.map(t => t.toString()).join(' '));

const soup = new JSSoup(html);

printTags(soup.findAll('p', 'foo'));
// <p class="foo">First</p> <p class="foo">Second</p>

printTags(soup.findAll('p', { class: 'foo' }));
// <p class="foo">First</p> <p class="foo">Second</p>

printTags(soup.findAll('p', { class: 'foo' }, 'Second'));
// <p class="foo">Second</p>

printTags(soup.findAll('p', { class: ['foo', 'bar'] }));
// <p class="foo">Second</p>

printTags(soup.findAll(null, 'bar'));
// <p class="foo bar">Second</p> <div class="foo">Third</div>

【讨论】:

  • @MarkusWeninger 在最底部添加了null(通配符)标签名称示例。
【解决方案2】:

根据文档,它似乎被称为findfindAll,具体取决于您要查找一个还是多个。这是他们给出的一个例子:

var data = `
<div>
  <p> hello </p>
  <p> world </p>
</div>
`
var soup = new JSSoup(data);
soup.find('p')
// <p> hello </p>

Looking at the source,我没有看到任何提供 CSS 选择器功能的东西,但它确实表明 findfindAll 接受多个参数,the documentation for BeautifulSoup 中的示例显示使用第二个参数进行过滤按班级,例如:

const JSSoup = require('jssoup').default;
const data = `
<div>
    <p class="foo bar"> hello </p>
    <p> world </p>
</div>
`
const soup = new JSSoup(data);
console.log(soup.find('p', 'foo').toString()); // Logs: <p class="foo bar">hello</p>

第二个参数也可以用于其他属性,但 CSS 选择器似乎不是一个选项。

您还有其他选项,例如 jsdom,它包含所有常见的 DOM 内容,例如 querySelectorquerySelectorAll

const { JSDOM } = require("jsdom");
const data = `
<div>
    <p class="foo bar"> hello </p>
    <p> world </p>
</div>
`;
const dom = new JSDOM(data);
const doc = dom.window.document;
console.log(doc.querySelector(".foo").outerHTML); // Logs: <p class="foo bar"> hello </p>

【讨论】:

  • 这似乎只适用于标签名称,但例如不适用于 CSS 类。例如mySoup.findAll('.myClass') 确实返回一个空数组,即使我有类myClass 的元素。
  • @MarkusWeninger - 看起来它稍微不仅仅是标签名称,但是的,不是完整的 CSS 选择器。我不想使用这个 API。 :-) 我可能会选择jsdom 或类似的,其中有querySelectorquerySelectorAll 等。
  • 感谢 jsdom 的提示!
【解决方案3】:

基于已经给出的答案,我只想补充:也可以通过在find()findAll() 中将标签名设置为undefined 来按类名(不带标签名)进行搜索:

mySoup.findAll(undefined, 'myClass');

【讨论】:

    猜你喜欢
    • 2018-03-31
    • 2014-07-06
    • 2011-11-14
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多