【问题标题】:How to know if web content cannot be handled by Scrapy?如何知道网页内容是否不能被 Scrapy 处理?
【发布时间】:2016-01-15 16:17:27
【问题描述】:

如果我的问题听起来太基本或太笼统,我深表歉意,但这让我困惑了很长一段时间。我是一名几乎没有 IT 背景的政治学家。我自己对这个问题的研究并没有解决这个难题。

据说 Scrapy 无法抓取 JavaScript 或 AJAX 生成的网页内容。但是我们怎么知道某些内容是否属于这一类呢?我曾经遇到过一些在 Chrome Inspect 中显示的文本,但无法被 Xpath 提取(我 99.9% 确信我的 Xpath 表达式是正确的)。有人提到这些文本可能隐藏在一些 JavaScript 后面。但这仍然是猜测,我不能完全确定这不是由于错误的 Xpath 表达式。是否有任何迹象可以让我确定这是 Scrapy 之外的东西,只能通过 Selenium 等程序处理?任何帮助表示赞赏。

-=-=-=-=-=

编辑(2015 年 1 月 18 日):我正在使用的网页是 http://yhfx.beijing.gov.cn/webdig.js?z=5。我要刮的具体信息是用红墨水圈出来的(见下图。对不起,是中文的)。

我可以在 Chrome 的 Inspect 中看到所需的文本,这表明要提取它的 Xpath 表达式应该是 response.xpath("//table/tr[13]/td[2]/text()").extract()。但是,表达式不起作用。

我在 Scrapy shell 中检查了response.body。所需的文本不在其中。我怀疑这里是 JavaScript 或 AJAX,但是在 html 中,我没有看到 JavaScript 或 AJAX 的迹象。知道它是什么吗?

【问题讨论】:

  • 终极刮刀:import.io
  • 好吧,如果 HTML 源代码中不存在某些内容(当然,如果其中有 JS 代码),您可以确定是由 JS 生成的。至于 99.9% 正确的 XPath 表达式 - 为什么不向我们展示它而不是说您已经看过 unicorn in the garden?并显示您尝试从中选择的 HTML。
  • @MathiasMüller,你是对的。我编辑了我的帖子并提供了网址。任何帮助表示赞赏。
  • @JosephZhou 我更喜欢使用“按标签查找值”的方法:response.xpath("//td[contains(.,"text in the label")]/following-sibling::td/text()")

标签: javascript selenium xpath scrapy


【解决方案1】:

据说 Scrapy 无法抓取 JavaScript 或 AJAX 生成的网页内容。但是我们怎么知道某些内容是否属于这一类呢?

当您打开网页时,浏览器会做很多事情。我将在这里过度简化流程:

  1. 向托管网页的服务器执行 HTTP 请求。
  2. 解析响应,在大多数情况下是 HTML 内容(基于文本的格式)。我们假设我们得到一个 HTML 响应。
  3. 开始呈现 HTML,执行 Javascript 代码,检索外部资源(图像、css 文件、js 文件、字体等)。不一定是这个顺序。
  4. 侦听可能触发更多请求以将更多内容注入页面的事件。

Scrapy 提供了执行 1. 和 2. 的工具。Selenium 和其他工具(如 Splash 执行 3.)允许您执行 4. 并访问呈现的 HTML。

现在,当您想从网页中提取文本内容时,我认为您面临三种基本情况:

  1. 文本为纯 HTML 格式,例如,作为文本节点或 HTML 属性:<a>foo</a><a href="foo" />。内容可以通过 CSS 或 Javascript 在视觉上隐藏,但只要是 HTML 树的一部分,我们就可以通过 XPath/CSS 规则提取它。
  2. 内容位于 Javascript 代码中。例如:<script>var cfg = {code: "foo"};</script>。我们可以使用 XPath 规则定位<script> 节点,然后使用正则表达式提取我们想要的字符串。还有一些库允许我们解析 Javascript 片段,以便我们可以轻松加载对象。这里有一个复杂的解决方案是通过 javascript 引擎执行 javascript 代码。
  3. 内容位于外部资源中,并通过 Ajax/XHR 加载。在这里,您可以使用 Scrapy 模拟 XHR 请求并解析输出,它可以是一个不错的 JSON 对象、任意 javascript 代码或只是 HTML 内容。如果对内容的检索/解析方式进行逆向工程变得棘手,那么您可以使用 Selenium 或 Splash 作为 Scrapy 的代理,这样您就可以访问渲染的内容,并且仍然可以将 Scrapy 用于您的爬虫。

你怎么知道你有哪种情况?您可以简单地在响应正文中查找内容:

$ scrapy shell http://example.com/page
...
>>> 'foo' in response.body.lower()
True

如果您通过浏览器在网页中看到foo,但上面的测试返回False,那么很可能内容是通过Ajax/XHR 加载的。您必须检查浏览器中的网络活动,查看正在执行哪些请求以及响应是什么。否则,您属于情况 1. 或 2。您只需在浏览器中查看源代码并搜索内容即可确定其位置。

假设您想要的内容位于 HTML 标记中。您如何知道您的 XPath 表达式是否正确? (这里的正确是指为您提供您期望的输出)

好吧,如果您执行scrapy shell 并且response.xpath(expression) 没有返回任何内容,那么您的XPath 不正确。您应该减少表达式的特异性,直到获得包含所需内容的输出,然后再缩小范围。

【讨论】:

  • 我非常感谢您的详细回答。我做了你建议的检查,我相信我的问题是案例 3。但你能否进一步说明如何检查浏览器中的网络活动并确保它是 Ajax/XHR? StackOverFlow 上有一篇关于此主题的帖子,但我无法掌握要查找的内容。非常感谢!
  • @JosephZhou 取决于您的浏览器,但基本上,在浏览器中打开检查器,选择network 选项卡并刷新/打开您的目标页面,然后您可以过滤 XHR 请求。在那里您可以看到请求有效负载和响应内容。另一个不太可能的情况是由外部 javascript(不是 XHR 请求)生成内容,为了找到它,我会下载整个网页并搜索(grep)文件以获取内容提示。您可能需要“美化”javascript 文件。
猜你喜欢
  • 2014-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 1970-01-01
  • 2021-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多