scrapy抓取动态页面的事项

最近在学习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自动化功能非常强大,还要继续学习啊!!!





发布了10 篇原创文章 · 获赞 7 · 访问量 9万+
展开阅读全文

请问HTML页面中如何动态获取数据

08-18

``` <form id="userinfofrm" action="${base}/member/index/douserinfo.htm" method="post" novalidate="novalidate"> <div class="personal-data"> <h3 class="gr-tit">个人资料</h3> <dl> <dt>头  像:</dt> <dd> <div class="head-pic"><img id="face" src="{$info['litpic']}" /><span class="upload">编辑头像</span></div> <input type="hidden" name="litpic" id="litpic" value="{$info['litpic']}"> </dd> </dl> <dl> <dt>昵  称:</dt> <dd> <input type="text" class="msg-text" id="nickname" name="nickname" value="{$info['nickname']}" /><span class="star-ico">*</span> </dd> </dl> <dl> <dt>性  别:</dt> <dd> <span class="sex"><a {if $info['sex']=='男'}class="on"{/if} href="javascript:;">男</a><a href="javascript:;" {if $info['sex']=='女'}class="on"{/if}>女</a></span> <input type="hidden" name="sex" id="sex" value="{$info['sex']}"> </dd> </dl> <dl> <dt>手机号:</dt> <dd> {if !empty($info['mobile'])} <span class="phone-num">{$info['mobile']}</span> <a class="revise" href="{$cmsurl}member/index/modify_phone?change=1">更换手机></a> {else} <a class="revise" href="{$cmsurl}member/index/modify_phone?change=1">绑定手机></a> {/if} </dd> </dl> <dl> <dt>E-mail:</dt> <dd> {if !empty($info['email'])} <span class="mail">{$info['email']}</span> <a class="revise" href="{$cmsurl}member/index/modify_email?change=1">更换邮箱></a> {else} <a class="revise" href="{$cmsurl}member/index/modify_email?change=1">绑定邮箱></a> {/if} </dd> </dl> <hr /> <dl> <dt>真实姓名:</dt> <dd><input type="text" name="truename" id="truename" class="msg-text" value="{$info['truename']}" /><span class="star-ico">*</span></dd> </dl> <dl> <dt>身份证号:</dt> <dd><input type="text" name="cardid" id="cardid" class="msg-text" value="{$info['cardid']}" /></dd> </dl> <dl> <dt>常住地址:</dt> <dd><input type="text" class="msg-text" name="address" id="address" value="{$info['address']}" /></dd> </dl> <div class="save-revise"> <a href="javascript:;" class="saveinfo">保存修改</a> </div> <div class="success-out-box" style=" display:none"> <div class="box-con"> <h3><img src="{$GLOBALS['cfg_public_url']}images/success-ico.png" />个人资料修改成功!</h3> <a href="javascript:;" class="close_success">确 定</a> </div> </div><!--修改成功弹出框--> <input name="backurl" type="hidden" value="${backurl!}" /> </div> </form> ``` 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览