如何知道Scrapy是否无法处理Web内容?

时间:2016-01-15 16:17:27

标签: javascript selenium xpath scrapy

如果我的问题听起来太基本或一般,我道歉,但它让我困惑了很长一段时间。我是一名IT背景很少的政治学家。我对这个问题的研究并没有解决这个难题。

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

- = - = - = - = - =

编辑(1/18/15):我正在使用的网页是http://yhfx.beijing.gov.cn/webdig.js?z=5。我要抓的特定信息用红色墨水圈出来(见下面的截图。抱歉,这是中文版)。

enter image description here

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

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

1 个答案:

答案 0 :(得分:3)

  

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

当您打开网页时,浏览器会执行很多操作。我将在这里简化过程:

  1. 对托管网页的服务器执行HTTP请求。
  2. 解析响应,在大多数情况下是HTML内容(基于文本的格式)。我们假设我们得到了一个HTML响应。
  3. 开始渲染HTML,执行Javascript代码,检索外部资源(图像,css文件,js文件,字体等)。不一定按此顺序。
  4. 收听可能触发更多请求以向网页注入更多内容的事件。
  5. 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用于您的爬虫。
    4. 你怎么知道你有哪些案件?您只需在响应正文中查找内容即可:

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

      如果您通过浏览器在网页中看到foo,但上面的测试返回False,那么内容可能是通过Ajax / XHR加载的。您必须在浏览器中检查网络活动,并查看正在执行的请求以及响应的内容。否则你就是1或2.你可以在浏览器中查看源代码并搜索内容以找出所在位置。

      假设您想要的内容位于HTML标记中。你怎么知道你的XPath表达式是否正确? (在这里更正,我们的意思是为您提供您期望的输出)

      好吧,如果你scrapy shellresponse.xpath(expression)没有返回任何内容,那么你的XPath就不正确了。您应该降低表达式的特异性,直到获得包含所需内容的输出,然后缩小范围。