更多>>关于我们
西安鲲之鹏网络信息技术有限公司从2010年开始专注于Web(网站)数据抓取领域。致力于为广大中国客户提供准确、快捷的数据采集相关服务。我们采用分布式系统架构,日采集网页数千万。我们拥有海量稳定高匿HTTP代理IP地址池,可以有效获取互联网任何公开可见信息。
您只需告诉我们您想抓取的网站是什么,您感兴趣的字段有哪些,你需要的数据是哪种格式,我们将为您做所有的工作,最后把数据(或程序)交付给你。
数据的格式可以是CSV、JSON、XML、ACCESS、SQLITE、MSSQL、MYSQL等等。
更多>>技术文章
通过控制IE进行自动化数据采集
发布时间:2012-10-28
通常我们直接使用HTTP协议与Web服务器进行交互,进行数据获取。
这种方法的优点是:
- 效率高,只需获取基本的HTML数据,不需要下载JS、CSS、Images等多余数据。
- 可控性强,可以根据需要加入、修改和读取任何报头;可以方便地使用代理进行轮换采集。
缺点是:
- 对于页面结构复杂,特别是使用JS动态生成内容的页面,数据提取难度大。
- 对于需要进行复杂认证(例如,证书)的网站,实现难度大。
本文介绍的通过控制IE浏览器进行数据采集的方法就可以绕过这些难点。
我们以“淘宝的量子横道店铺经自动报表导出”为例,其实现主要难点有两个:
1)登录需要验证证书。
解决方法:我们需要在IE下登录支付宝安装一下用户证书。在登录表单页通过DOM操作录入用户名和密码,并触发登录按钮点击事件,完成自动登录。
2)报表是Ajax动态加载的。Ajax数据源路径里有一不定参数,难以确定其如何产生。
解决方法:控制IE访问报表地址,等待Ajax内容加载完毕,获取页面HTML。
部分示例代码:
# coding: utf-8 import time import win32com.client def _wait(ie): """等待页面加载完毕 """ while ie.Busy: time.sleep(1) def wait_flag(ie, flag, timeout=20): """等待标志字符出现 """ start = time.time() while flag not in ie.Document.body.innerHTML and time.time() - start < timeout: time.sleep(2) def getElementById(ie, item, _id): """兼容IE9的写法 注意:IE9不支持getElementById!!!这也是我不直接使用PAMIE库的原因。 """ for element in ie.Document.body.getElementsByTagName(item): if str(element.getAttribute("id")) == _id: return element def login(username, password): """登录量子横道经 """ ie = win32com.client.Dispatch("InternetExplorer.Application") ie.Visible = 1 # 打开登录表单 try: ie.Navigate('https://login.taobao.com/member/login.jhtml?_input_charset=utf-8&from=lzdp&style=minisimple&minipara=0,0,0&redirect_url=http%3A%2F%2Flz.taobao.com%2Flogin%2F%3F') _wait(ie) if getElementById(ie, 'button', 'J_SubmitStatic'): # 去掉“安全控件登录”复选框,否则无法自动录入密码 checkbox = getElementById(ie, 'input', 'J_SafeLoginCheck') if checkbox and checkbox.checked: print 'J_SafeLoginCheck checked.' #checkbox.checked = False checkbox.click() time.sleep(5) else: print 'J_SafeLoginCheck not checked.' # 输入密码 getElementById(ie, 'input', 'TPL_username_1').value = username getElementById(ie, 'input', 'TPL_password_1').value = password # 提交登录 getElementById(ie, 'button', 'J_SubmitStatic').click() _wait(ie) # 等待足够长的时间 time.sleep(15) wait_flag(ie=ie, flag=u'退出') if u'验证码' in ie.Document.body.innerHTML: common.logger.info('Need to enter captcha. Failed to scrape.') ie.quit() return -1 if u'请输入您的密码' in ie.Document.body.innerHTML: common.logger.info('Failed to enter password.') ie.quit() return -1
使用控制浏览器进行数据采集,只适合这种少量页面数据的采集:
- 难以实现多线程,因为多个浏览器窗口也是共享同一会话,会互干扰。
- 难以切换代理。
后面我们会再介绍一种调用浏览器内核(webkit)进行数据采集的方法,它既能支持多线程也能方便地进行代理切换。
特别说明:本文旨在技术交流,请勿将涉及的技术用于非法用途,否则一切后果自负。如果您觉得我们侵犯了您的合法权益,请联系我们予以处理。
☹ Disqus被Qiang了,之前所有的评论内容都看不到了。如果您有爬虫相关技术方面的问题,欢迎发到我们的问答平台:http://spider.site-digger.com/