Python数据网络采集5--处理Javascript和重定向

到目前为止,我们和网站服务器通信的唯一方式,就是发出HTTP请求获取页面。有些网页,我们不需要单独请求,就可以和网络服务器交互(收发信息),那么这个网页可能采用了Ajax技术来加载数据。使用以前的采集方法,可能只能采集到加载之前的数据,重要的数据就抓不到了。

和Ajax一样,动态HTML(DHTML)也是一系列用于解决网络问题的技术集合。DHTML用客户端语言,如JavaScript控制页面的HTML元素。经常,在我们采集网站时,从浏览器中看到的内容,和爬取到的内容就是不一样。或者网页用一个加载页把我们引到另外一个页面上,但是URL链接在这个过程中却一直没有变化。

这些都是因为网页中的JavaScript在作怪。浏览器可以正确执行JavaScript,但是我们在爬取过程中,也许直接就忽视了这些代码。所以导致浏览器中看到的和爬取到的内容不一样。

Ajax/DHTML技术给爬虫带来了困难,不过可以使用Selenium可以方便处理页面中的JavaScript代码。

来看个例子, 下面访问的网页使用了Ajax技术加载,大概2秒左右页面内容会改变(但是地址栏的URL链接没有改变)。

import requests

from bs4 import BeautifulSoup

url = 'http://pythonscraping.com/pages/javascript/ajaxDemo.html'

r = requests.get(url)

soup = BeautifulSoup(r.text, 'lxml')

content = soup.find('div', id='content')

print(content.string)

This is some content that will appear on the page while it's loading. You don't care about scraping this.

Selenium处理JavaScript

实际上,如果在浏览器打开这个页面,最后显示的内容不是这样的。刚开始是会显示这些内容,不过马上就被新的内容取代了。可以试试等待个几秒。上面的例子中使用requests访问,是立即返回了响应的,所以只能获取到加载前的内容。所以若是要等待,requests好像就没那么好使了。上Selenium吧!

import time

from selenium import webdriver

driver = webdriver.PhantomJS(executable_path=r'C:\Program Files (x86)\phantomjs\bin\phantomjs.exe')

driver.get('http://pythonscraping.com/pages/javascript/ajaxDemo.html')

# 等待加载完成

time.sleep(5)

content = driver.find_element_by_id('content').text

print(content)

driver.quit()

Here is some important text you want to retrieve!

A button to click!

上面使用到了PhantomJs,就是一个没有界面的浏览器,和Selenium结合使用十分方便。PhantomJs需要下载。

WebElement有个属性text可以获得标签内的文本。看上面的打印信息,确实新的内容加载出来了。在使用时,需要指定phantomjs所在的目录。而且,因为没有界面,在使用完后记得close或者quit。

上面的代码限制了5秒后查找元素,但是页面到底什么时候加载好是不能确定的。所以可以不断检测页面某个内容是否已经加载完毕。

from selenium import webdriver

from selenium.webdriver.support.wait import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

from selenium.webdriver.common.by import By

driver = webdriver.PhantomJS(executable_path=r'C:\Program Files (x86)\phantomjs\bin\phantomjs.exe')

driver.get('http://pythonscraping.com/pages/javascript/ajaxDemo.html')

try:

element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'loadedButton')))

print(element)

finally:

print(driver.find_element_by_id('content').text)

driver.close()

Here is some important text you want to retrieve!

A button to click!

这里使用了WebDriverWait和expected_conditions来构成隐式等待。隐式等待就是等DOM中某个状态发生后再继续运行代码,没有明确的等待时间,但是有最大等待时限(上例中时10s),而显式等待就是指定了等待时间的,如前面有个例子指定了sleep(5)。expected_conditions指定了期望的条件,上面的例子是一直等待,直到id为loadedButton的元素显示出来。By是选择器,可以按照下面的方式查找。

ID = "id"

XPATH = "xpath"

LINK_TEXT = "link text"

PARTIAL_LINK_TEXT = "partial link text"

NAME = "name"

TAG_NAME = "tag name"

CLASS_NAME = "class name"

CSS_SELECTOR = "css selector"

其实下面两句的意思是一样的:

driver.find_element(By.ID, 'loadedButton')

driver.find_element_by_id('loadedButton')

Xpath语法

还能使用Xpath的语法进行查找。下面列举一些常用的语法。

/div 选择根节点是div的元素

//a 选择文档中的所有a节点(包括非根节点)

//@href 选择带有href属性的所有节点

//a[@href='https://www.google.com'] 选择所有具有href为google网站的a标签

//a[3] 选择文档中第3个a标签

//table[last()] 选择文档中最后一个table

//a[position() < 3] 选择文档中的前三个a标签

处理重定向

重定向分为客户端重定向(Redirect)和服务端重定向(Dispatch),后者意思为派遣,就是常说的转发。转发只请求了一次,所以Python的requests能轻松处理,但是重定向的话,请求了两次,url一般会变化。这时候需要使用Selenium了。下面的例子可以监视链接是否已经重定向了,使用的方法是,首先从页面开始加载的时候就监视DOM中的某一个元素,然后重复查找这个元素,检查它和原来的元素是不是同一个,直到抛出StaleElementReferenceException,就是说元素已经不在页面的DOM里了,此时已经跳转。

import time

# Stale means the element no longer appears on the DOM of the page

from selenium.common.exceptions import StaleElementReferenceException

from selenium import webdriver

def wait_for_load(a_driver):

element = a_driver.find_element_by_tag_name('html')

print('content', element)

count = 0

while True:

count += 1

# 超过10s,直接返回

if count > 20:

print('Timing out after 10s and returning')

return

time.sleep(0.5) # 检查还是不是同一个element,如果不是,说明这个html标签已经不再DOM中了。如果不是抛出异常

new = a_driver.find_element_by_tag_name('html')

print('new', new)

if element != new:

raise StaleElementReferenceException('刚才重定向了!')

driver = webdriver.PhantomJS(r'C:\Program Files (x86)\phantomjs\bin\phantomjs.exe')

driver.get('https://pythonscraping.com/pages/javascript/redirectDemo1.html')

try:

wait_for_load(driver)

except StaleElementReferenceException as e:

print(e.msg)

finally:

print(driver.page_source)

content

new

new

new

new

new

new

new

刚才重定向了!

The Destination Page!

This is the page you are looking for!

我们打印了刚刚进入网页时候的html元素对应的WebElement的wdc。wdc:1500305464563相当于是个id。

在循环中不断检测是否和原来的WebElement是否为同一个,如果不是,那么已经发生了重定向。发生重定向前,wdc已经改变为wdc:1500305468142。之后页面跳转到了redirectDemo2.html。

by @sunhaiyu

2017.7.17

python 访问网页 重定向_Python数据网络采集5--处理Javascript和重定向相关推荐

  1. python访问网页速度_python实现用于测试网站访问速率的方法

    这是python编写的用于测试网站访问速率的代码片段,可以输出打开某url的时间,访问100次的平均时间,最大时间和最小时间等等 import urllib2 from datetime import ...

  2. python访问网页变量_Python 如何访问外围作用域中的变量

    在表达式中引用变量时,Python 会按照如下的顺序遍历各个作用域,寻找该变量: 当前函数作用域 任何外围作用域(比如包含当前函数的其他函数) global 作用域,即代码所在的模块的作用域 如果上述 ...

  3. python访问网页被拒_Python Requests.get访问网页403错误

    Pycharm 2018.1, Python 3.6, 通过Pycharm的File->Settings->Plugins搜索Requests安装上去. import requests r ...

  4. python获取网页图片_python抓取网页中的图片示例

    python抓取网页中的图片示例 代码如下: #coding:utf8 import re import urllib def getHTML(url): page = urllib.urlopen( ...

  5. python爬虫网页表格_python网页表格

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 以网页表格为例:https:www.kuaidaili.comfree该网站数据 ...

  6. python访问共享文件夹_python – 通过linux机器打开Windows共享文件夹

    我在Ubuntu上使用python 2.5,并且在同一网络中有一台名为machine1的机器.该文件夹是共享的. 如何在该机器的特定文件夹中获取文件? 我试过了,没有成功: urllib.urlope ...

  7. python爬虫网页超链接_Python爬虫获取网页上的链接

    Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.利用Beautiful Soup可以对网页进行解析,提取所有的超链接. Beautiful Soup提供一些简单的.p ...

  8. python获取网页图片_Python获取网页上图片下载地址的方法

    本文实例讲述了Python获取网页上图片下载地址的方法.分享给大家供大家参考.具体如下: 这里获取网页上图片的下载地址是正在写的数据采集中的一段,代码如下: #!/user/bin/python3 i ...

  9. python windows自动化 爬虫_Python体系(网络爬虫、人工智能、WEB开发、自动化运维)详细介绍...

    不论你是对Python初出茅庐,还是如指诸掌,这篇文章对你的收获总归还是有的啦,可能只是程度的问题.好了不扯远了,来说正题,下面在分享这套体系前还是要让Python做一下"自我介绍" ...

最新文章

  1. 如何查看哪些参数被新版本抛弃了?
  2. 企业管理软件能带来什么
  3. MySQL入门之创建、修改、删除、查看数据库
  4. PSPNet网络要点
  5. 一个简单的静态web服务器
  6. NetBeans 成为 Apache 软件基金会顶级项目
  7. [20170612]FOR ALL COLUMNS SIZE repeat12c
  8. 氩焊机器人编程_如何操作焊接机器人的编程?这六点是基础!
  9. VB使用API的简明教程
  10. java贪吃蛇代码_求Java贪吃蛇代码
  11. smtp服务器组件,本机搭建虚拟SMTP服务器教程
  12. ENVI中FLAASH大气校正中的Atmosphere Model选项各含义
  13. 最新2022中国大学排名发布!
  14. python 实现接口上传图片
  15. mysql三表联合查询(员工表,部门表,工资表)
  16. 2003版excel 删除某列数据相同的行只保留一行的方法
  17. 苹果CMS搭建影视网站教程
  18. 利用http://www.forshare.me/qq/访问陌生人的QQ空间
  19. Unity3D摄像机跟随人物移动脚本
  20. RXTXcomm.jar 读取串口数据时报 Underlying input stream returned zero bytes 异常解决方法

热门文章

  1. tar: Cowardly refusing to create an empty archive 问题
  2. sample java_从sample来学习Java堆(转)
  3. python goto 用法
  4. ubuntu16.0.4 opencv4.0.0 GPU 版本的 SURF
  5. python操作neo4j
  6. LeetCode 77. Combinations--回溯法,-Python,Java解法
  7. Linux在shell终端中清空DNS缓存,刷新DNS的方法(ubuntu,debian)
  8. c语言里的多参数吗,C语言中不定参数的实现
  9. linux图形登陆报拒绝权限,Linux-权限被拒绝?
  10. oracle 10g磁盘管理,Oracle 10g UNDO表空间过大导致磁盘空间不足的解决