抓取网页数据违法吗(通过selenium的子模块使用Python爬取网页数据的解决思路)
优采云 发布时间: 2021-10-08 03:08抓取网页数据违法吗(通过selenium的子模块使用Python爬取网页数据的解决思路)
1. 文章 目的
我们在使用Python爬取网页数据时,经常会用到urllib模块,它通过调用urllib模块的urlopen(url)方法返回网页对象,并使用read()方法获取网页的html内容url,然后使用 BeautifulSoup 抓取某个 Label 内容,结合正则表达式过滤。然而,你用 urllib.urlopen(url).read() 得到的只是网页的静态html内容,还有很多动态数据(比如访问量网站,当前在线人数,微博上的点赞数等)不收录在静态html中,比如我想在这个bbs网站中抓取当前每个版块的在线数,静态html网页不收录它(不信,请查看页面源码,只有简单的一行)。
2. 解决方案
我试过网上提到的浏览器自带的开发者工具(一般是F12弹出相应网页的开发者工具)来查看网上动态数据的趋势,但这需要从很多网址中寻找线索。个人觉得太麻烦。另外,查看器查看的html内容也收录动态数据,但是有几个问题:如何实时获取查看器的html内容?如何将查看器的html导入python程序?因此,使用查看器的html内容的方法也不符合爬虫的要求。
偶然发现了selenium模块,发现这个模块可以很方便的根据url加载页面获取session,找到当前session对应的tag。本文将使用 selenium webdriver 模块来获取这些动态生成的内容,尤其是一些重要的动态数据。事实上,selenium 模块的功能不仅限于抓取网页。它是网络自动化测试的常用模块。它在 Ruby 和 Java 中被广泛使用。Python虽然使用的相对较少,但它也是一个非常简单、高效、易用的自动化测试。模块。通过使用selenium的子模块webdriver解决动态数据的捕获问题,你也可以对selenium有一个基本的了解,为进一步学习自动化测试打下基础。
3. 实现过程 3.1 运行环境
我在windows 7系统上安装了Python2.7版本,使用的是Python(X,Y)的IDE,安装的Python库没有自带selenium,直接在Python程序中导入selenium会提示没有这样的模块,在联网状态下,cmd直接输入pip install selenium,系统会找到Python的安装目录,直接下载解压安装这个模块。终端提示完成后,可以查看C:\Python27\Lib\site-packages目录下是否有selenium模块。这个目录取决于你安装 Python 的路径。如果有 selenium 和 selenium-2.47.3.dist-info 两个文件夹,则可以在 Python 程序中加载模块。
使用 webdriver 捕获动态数据
先导入webdriver子模块
from selenium import webdriver 获取浏览器会话,浏览器可以使用火狐、Chrome、IE等,这里以火狐为例
browser = webdriver.Firefox() 加载页面,url本身可以指定合法字符串
browser.get(url) 获取到 session 对象后,为了定位元素,webdriver 提供了一系列的元素定位方法。常用的方法有以下几种:
ID
姓名
班级名称
关联
文本
部分的
关联
文本
标签
姓名
路径
css选择器
比如通过id定位,返回一个所有元素组成的列表,lis=borwser.find_elements_by_id_name('kw'')
按类名定位,lis=find_elements_by_class_name('title_1')
更详细的定位方法请参考selenium webdriver(python)教程-定位方法部分第三章(第一版可在百度文库阅读)结合正则表达式过滤相关资料
定位后有些元素是不需要的,有规律的过滤掉即可。比如我想只提取英文字符(包括0-9),建立如下规律
pa=堆(r'\w+')
对于 lis 中的你:
en=pa.findall(u.lis)
打印结束会话
执行fetch操作后必须关闭session,否则让它一直占用内存会影响机器上其他进程的操作
Browser.close() 或 browser.quit() 可以关闭会话。前者只是关闭当前会话而不关闭浏览器的webdriver,后者关闭包括webdriver在内的所有东西并添加异常处理。
这个是必须的,因为有时候会获取session失败,所以把上面的语句块放到try里面,然后用exception处理
除了 NoSuchElementException:
assert 0, "找不到元素"4. 代码实现
我通过点击打开链接抓取指定分区的每个版块的在线用户数,并指定分区id号(0-9),可以得到该版块的名称和对应的在线号,以及以列表的形式打印出来,代码如下
[Python]
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
import time
import re
def find_sec(secid):
pa=re.compile(r'\w+')
browser = webdriver.Firefox() # Get local session of firefox
browser.get("http://bbs.byr.cn/#!section/%s "%secid) # Load page
time.sleep(1) # Let the page load
result=[]
try:
#获得版面名称和在线人数,形成列表
board=browser.find_elements_by_class_name('title_1')
ol_num=browser.find_elements_by_class_name('title_4')
max_bindex=len(board)
max_oindex=len(ol_num)
assert max_bindex==max_oindex,'index not equivalent!'
#版面名称有中英文,因此用正则过滤只剩英文的
for i in range(1,max_oindex):
board_en=pa.findall(board[i].text)
result.append([str(board_en[-1]),int(ol_num[i].text)])
browser.close()
return result
except NoSuchElementException:
assert 0, "can't find element"
print find_sec('5') #打印分区5下面的所有板块的当前在线人数列表
操作结果如下:
终端打印效果
4. 总结
Selenium 在代码简洁性和执行效率方面非常出色。使用 selenium webdriver 捕获动态数据非常简单高效。还可以进一步利用它来实现数据挖掘和机器学习等深度研究。因此,selenium+python 是值得深入研究的!如果觉得每次都用selenium打开浏览器不方便,可以用phantomjs模拟虚拟浏览器,这里不再赘述。