scrapy抓取动态页面的事项

时间:2021-10-08 09:23:07

最近在学习scrapy抓取动态js加载页面,写此作以记录。

scrapy需要的环境有python2.7+lxml+pyopenssl+twisted+pywin32等,网上都有教程可参考http://www.cnblogs.com/zhxhdean/p/3580224.html、http://blog.csdn.net/playstudy/article/details/17296473等等,注意,pyopenssl.whl安装的时候需要用 pip install ...whl 另外,若用到mysql还需安装mysqldb模块。

最好的安装教程:http://my.oschina.net/leezhen/blog/200264

  • 执行import lxml,如果没报错,则说明lxml安装成功
  • 执行import twisted,如果没报错,则说明twisted安装成功
  • 执行import OpenSSL,如果没报错,则说明OpenSSL安装成功
  • 执行import zope.interface,如果没报错,则说明zope.interface安装成功
  • 如果安装成功,那么在cmd中执行& python,然后执行import lxml,如果没有报错,则说明lxml安装成功。
补充: 在scrapy1.1中支持python3了,官方文档说是只支持linux环境下的python3,但是也可以在windows下尝试也是可以的,参考https://zhuanlan.zhihu.com/p/21335106,中间需要手动下载lxml,用pip install ...whl执行安装,再手动安装pypiwin32,然后导入twisted的那两个文件就可以了。

入门的教程就看官方文档就可以,http://doc.scrapy.org/en/latest/intro/tutorial.html英文原版、https://scrapy-chs.readthedocs.org/zh_CN/0.24/topics/selectors.html#topics-selectors-htmlcode中文版。

xpath是scrapy内置的一种相对简易的dom解析方法,但时作为用惯了php的simple_html_dom解析的人,对xpath还是很有偏见的,xpath太严格了,不能越级查询,必须一层一层解析,xpath虽然很麻烦,但也相对不易犯错。response.xpath().extract()和response.xpath().re()执行出来都是list形式,这点需要注意,在存数据库的时候需要注意。另外,其执行出来会通过Unicode编码,貌似在re()中进行正则匹配的时候还是需要re(u''),貌似是这样的,这点还没有完全搞清楚,在网上也见过有这样的写法re(r''),待研究。。。

还有一种解析的方法,也是scrapy内置的css选择器,具体的选择文档可以去w3cschool上查阅,这里着重说一个选择的方法,如:li:nth-of-type(2) 是选择了第二个li节点


在此次用scrapy的过程中,重点学习了如何抓取动态js加载的页面。现在很多网站都是源码中没有太多的信息,主要的信息是从js文件中加载后才能在审查元素中找到的。

所以现在需要一个模拟浏览器的东西,phantomjs就是一个模拟浏览器的利器,phantomjs是一个小型的浏览器内核,调用它可以非常方便快速的进行解析。

cmd = 'phantomjs constructDom.js "%s"' % response.url
print "cmd:",cmd
stdout,stderr = subprocess.Popen(cmd,shell= True,stdout = subprocess.PIPE,stderr = subprocess.PIPE).communicate()
sel = Selector(text=stdout)
constructDom.js是一个解析网页的js,这是在网上的一段代码,拿来使用了
var page = require('webpage').create(),system = require('system'),address;if(system.args.length === 1){phantom.exit(1);}else{address = system.args[1];page.open(address, function (status){if(status !== 'success'){phantom.exit();}else{var sc = page.evaluate(function(){return document.body.innerHTML;});window.setTimeout(function (){console.log(sc);phantom.exit();},1000);}});}
上面这四句就展示一个调用的过程,这里只是调用了一下它的接口,关于phantomjs太深入的东西还没有了解。
有时候需要让页面停留一段时间以等待加载,这时候得需要js代码sleep一段时间,但是js又没有sleep这个方法,而setTimeOut相当于另起了一个线程,并不能实现所需的sleep功能,下面一段代码可以间接的实现sleep的功能,相当于sleep了1秒钟。
var t = Date.now();

function sleep(d){
<span style="white-space:pre"></span>while(Date.now - t <= d);
}
sleep(1000);
但是有时候数据是通过ajax的方式才加载出来的,我们并不知道应该sleep多长的时间,因此,最好的解决方法就是找到数据传输的接口,通过访问接口得到想要的数据,一般会返回json数据,用下面这句代码可以实现python解析json数据并转换为Unicode格式
data = json.loads(response.body_as_unicode())

 
另外,有时候我们还要模拟点击,上下滑动等方法,这时候就需要selenium这个调用可视化浏览器的利器,它默认调用firefox。
<span style="white-space:pre"></span><pre style="background-color: rgb(255, 255, 255); font-family: 宋体; font-size: 12pt;"><pre name="code" class="python">from selenium import webdriver
 
<span style="white-space:pre"></span>driver = webdriver.Firefox() #调用火狐浏览器
driver.get(response.url)
js="var q=document.documentElement.scrollTop=10000" #滑动到页面最底部
i=0
while(i<10):
try:
driver.execute_script(js)
driver.find_element_by_class_name("block-loading")
time.sleep(1)
i+=1
except Exception,e:
break
sel = Selector(text=driver.page_source)
driver.quit()
driver = None

webdriver就是selenium中的一个方法,上面这段代码使用调用火狐浏览器,然后再模拟滑动滚动条到最底部,有些页面是边滑动边加载的,这时候就需要这种发放。比如蚂蜂窝,可能需要滑动若干次才能加载完整的页面,新浪微博也是这样的情况。quit()读取完成后关闭浏览器。

selenium的api详解:http://blog.csdn.net/collonn/article/details/12656677

 
selenium配合js会让UI自动化功能非常强大,还要继续学习啊!!!