python 模拟浏览器selenium_使用Selenium模拟浏览器,实现自动爬取数据

最近需要在一个网站下载一批数据。但是输入一个查询,返回三四万条结果,每次只能导出500条,而且每次还得输入下载条目的范围!这样点击下载,还不要了我的老命。于是乎想自动化这个过程。

我的需求主要是两点:1. 要求自动化程度高。最好有直接模拟浏览器鼠标和键盘动作的成熟接口,比如在文本框输入,选择下拉列表,单选框,复选框,点击按钮等。2. 不要求效率。因为我要的数据量相对来说很小。3. python下的框架。因为平时几乎主要用python。

我不太懂网站技术,和网站沾边的经验只有两个:开发过一个很简单安卓的客户端,用python的scrapy框架写过爬虫来自动爬取新闻。所以了解一些客户端和服务端基本的交互方式、了解如何分析网页源代码、了解xpath语法。

刚开始针对这个问题,我连搜啥都不太清楚。知乎的这篇文章提供了很多有用信息:“Python 爬虫如何获取 JS 生成的 URL 和网页内容?” 顺着它我又权衡了很多方法,最后选择了Selenium。主要优点是学习成本极小,代码实现快。缺点是爬取效率低。想要高效率的朋友,就要花一些时间学习更复杂的工具包了。

网站技术

想要自动爬取网页,得了解一些基本的知识,这样做起来更快。这里简单介绍一下相关知识。

1. Request/response

request是客户端向服务端发起请求。输入一个网址对应一个request动作,这是最直观的。爬取静态网页的内容,只要知道网址就可以了。但是现在的网页很多都是动态的,鼠标指向或者点击网页中某些元素也会触发request动作,从而使网页动态更新部分内容,这部分内容是不能直接从静态网页中获取的。这种技术叫AJAX,不过我不太懂。这里的问题是我们可能根本不知道网址是什么,因此需要一些高级的接口,能处理动态内容。

response是服务端给客户端的返回内容。想要获取静态网页内容的话,直接从requeson里取就好了。

beb200cda628

2. 分析网页源码

我们想要爬取网页上的某一部分信息,需要知道如何能定位到它。这里需要HTML,XPATH的知识。不知道的可以上w3school 在线教程:http://www.w3school.com.cn

查看网页源代码,鼠标指针指向网页任意地方,或者指向目标元素。右键鼠标,在下拉列表选择“检查元素”即可。如下是我右键“百度一下”所显示的网页源代码,是HTML格式的,我们可以看到对应的HTML代码。把它提取出来,我们可能需要div//@[class="head_wrapper"]//input[@type="submit"]的语句,这是XPATH语法,很好掌握。知道如何分析网页,我们又进了一步。

beb200cda628

3. 网页基本元素操作

前进、后退、刷新、打开新选项卡、输入网址等;

文本框输入、选择下拉列表、单选框、复选框、点击按钮等。

我这里需要模拟的操作也就这么多了,对应的selenium接口可以参考 http://www.cnblogs.com/Ming8006/p/5727542.html。

4. Selenium介绍

一句话:Selenium是一个web应用的自动化测试工具集。

好多句话:Selenium 诞生于 2004 年,当在 ThoughtWorks 工作的 Jason Huggins 在测试一个内部应用时。作为一个聪明的家伙,他意识到相对于每次改动都需要手工进行测试,他的时间应该用得更有价值。他开发了一个可以驱动页面进行交互的 Javascript 库,能让多浏览器自动返回测试结果。那个库最终变成了 Selenium 的核心,它是 Selenium RC(远程控制)和 Selenium IDE 所有功能的基础。

实战练习

1.分析数据获取的过程

我的数据获取过程如下:

在A页面输入查询语句,点击submit;浏览器自动新开一个页面,跳转到新页面B,在文本框输入下载条目的范围;点击Export弹出弹窗,然后在下拉列表、单选框、复选框做一些选择,点击下载。然后浏览器就开始下载文件了。

网页A

beb200cda628

网页B

beb200cda628

2. 爬取过程

A. 安装Selenium

Selenium支持多种浏览器,我选用google chrome。下载地址:https://sites.google.com/a/chromium.org/chromedriver/。同时,当然要在python中安装selenium。 命令行输入pip install senenium 即可安装。

B. 配置环境变量

这一步需要将chromedriver的保存路径配置到操作系统的环境变量中,好让selenium能找到chromedriver。windows下配置环境变量PATH,linux或者mac可以选择配置到 .bash_rc中。配置方法很多,自行百度。

我用的是mac,不知为什么配置了不起作用!后来发现只有在代码里设置才能起作用。

C. 核心代码(python)

# 设置下载路径,将路径配置到ChromeOptions。

chromeptions = webdriver.ChromeOptions()

prefs = {'profile.default_content_settings.popups':0,'download.default_directory': query_dir}

chromeptions.add_experimental_option('prefs', prefs)

# 设置环境变量,启动浏览器。

chromedriver = CHROMEDRIVER_DIR    # 设置成你自己的路径

os.environ["webdriver.chrome.driver"] = chromedriver

driver = webdriver.Chrome(executable_path=chromedriver,chrome_options=chromeptions)

# 设置隐形等待时间,因为点击后网站一段时间后才能返回内容,如果不等待会报超时异常。

driver.implicitly_wait(IMPLICIT_WAIT_TIME)

# 请求网页A

driver.get("http://demo.ovid.com/demo/ovidsptools/launcher.htm")

# 在网页A的两个文本框输入,并提交。

beb200cda628

driver.find_element_by_name('D').clear()

driver.find_element_by_name('D').send_keys('mesz')

driver.find_element_by_name('SEARCH').clear()

driver.find_element_by_name('SEARCH').send_keys(str_search_query)

driver.find_element_by_name('ovid').click()

#  跳转到新窗口,并将焦点定位到该窗口。

current_window_handle = driver.current_window_handle

for hdl in driver.window_handles:   # selenium总是有两个handle

if hdl != current_window_handle:

new_window_handle = hdl

driver.switch_to.window(new_window_handle)

driver.implicitly_wait(IMPLICIT_WAIT_TIME)

# 获取到网页。首先获取返回的总条目数,然后提取文本框输入下载条目的范围,如1-500。然后点击Export。

beb200cda628

# 注意:等待页面加载完成后再计算下载次数

search_ret_num = WebDriverWait(driver, EXPLICIT_WAIT_TIME,  EXPLICIT_WAIT_INTERVAL).until(EC.presence_of_element_located((By.XPATH,'//*[@id="searchaid-numbers"]')))

search_ret_num =int(re.findall(r'\d+', search_ret_num.text.encode('utf-8'))[0])

list_range = chunks_by_element(range(1, search_ret_num+1), DOWNLOAD_NUM_PER_TIME)

for item in list_range:

download_range = driver.find_element_by_xpath('//*[@id="titles-display"]//input[@title="Range"]')

download_range.clear()

download_range.send_keys('{}-{}'.format(item[0], item[-1]))

# 点击 Export

export = driver.find_element_by_xpath('//*[@id="titles-display"]//input[@value="Export"]')

export.click()

# 获取到弹窗。进行一些设置。

beb200cda628

driver.switch_to.alert

WebDriverWait(driver, EXPLICIT_WAIT_TIME, EXPLICIT_WAIT_INTERVAL).until(EC.presence_of_element_located((By.XPATH,'//div[@id="export-citation-popup"]')))

# 设置下载文件的一些配置

export_to_options = driver.find_element_by_xpath('//select[@id="export-citation-export-to-options"]')

export_to_options.find_element_by_xpath('//option[@value="xml"]').click()# XML

# 设置 citation content radio

citation_options = driver.find_element_by_xpath('//ul[@id="export-citation-options"]')

citation_options.find_element_by_xpath('//input[@value="ALL"]').click()#  Complete Reference

# 设置 include check-box

citation_include = driver.find_element_by_xpath('//div[@id="export-citation-include"]')

ifcitation_include.find_element_by_xpath('//input[@name="externalResolverLink"]').is_selected():# Link to External Resolver

citation_include.find_element_by_xpath('//input[@name="externalResolverLink"]').click()

ifcitation_include.find_element_by_xpath('//input[@name="jumpstartLink"]').is_selected():# Include URL

citation_include.find_element_by_xpath('//input[@name="jumpstartLink"]').click()

ifcitation_include.find_element_by_xpath('//input[@name="saveStrategy"]').is_selected():# Search History

citation_include.find_element_by_xpath('//input[@name="saveStrategy"]').click()

# 点击下载。

download = driver.find_element_by_xpath('//div[@class ="export-citation-buttons"]')

download.click()

finally:

sleep(30)# wait for finishing downloading the last file

# driver.implicitly_wait(30) # doesn't work!

driver.quit()

return

3. 小贴士

A. 每次启动一个浏览器,桌面就会真的弹出一个浏览器。你可以清晰地看到自动化过程是如何的。看来selenium真的就是为web程序的自动化测试准备的。另外,爬取过程中要注意屏幕保持打开。如果进入休眠或者屏保,也会抛出异常的。

B. 模拟网页操作的时候,网页跳转是很常见的场景。因此要注意网页响应时间。selenium不会等待网页响应完成再继续执行代码,它会直接执行。二者应该是不同的进程。这里可以选择设置隐性等待和显性等待。在其他操作中,隐性等待起决定性作用,在WebDriverWait..中显性等待起主要作用,但要注意的是,最长的等待时间取决于两者之间的大者,如果隐性等待时间 > 显性等待时间,则该句代码的最长等待时间等于隐性等待时间。

C. 设置下载路径时,刚开始怎么都不起作用。我怀疑是key “download.default_directory”不对,于是通过查看网页源代码,找到了key,依然一样的。问题出在其他地方。不过这里提醒了我,以后在代码中用字典做相关的配置时,可以通过查看源代码的方式来猜测。

beb200cda628

D. 原以为实现整个过程最起码的两三天,因为我真的不懂。从开始学习到做完不到一个白天就完成了。估计是因为我动手之前搜了很长时间,反复比对之后,找了个最得心应手的工具。

E. 完成后我在github上搜了一圈,发现了一个神器https://github.com/voliveirajr/seleniumcrawler。 对于想爬取大量内容的朋友,如果还不想浪费时间学习太多web应用底层的知识,可以结合使用Selenium+scrapy。scrapy可以负责搜索网页,selenium负责处理每个网页上的内容,尤其是动态内容。下次我如果有需求,打算用这个思路了!

F. 分享一句话。“关于爬虫,涨经验最快的方式是:学学怎么写网站,你知道网站是什么发请求的,就知道怎么爬网站了!” 很简单吧,不过这么简单的一句话给我很大的启发。之前就是感觉太难,一直停留在scrapy爬取静态网页的水平。而且像cookies之类的技术也看了,看一次忘一次。现在看来,还是因为没有把网站的整体流程梳理清楚。另一方面,也是畏惧那些繁杂的网站技术名词。其实只要上网查查相关的概念怎么回事,慢慢就打通了。

G. 最后,完全不懂编程的人可以用一些可视化的爬虫工具,这里有一些介绍:https://www.sdk.cn/news/4801。懂编程的且想要高效率的就需要参考其他工具了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值