赞
踩
目录
lxml
库是一款 Python 数据解析库,参考重要文档在 lxml - Processing XML and HTML with Python,
在解析数据的时候,大量的代码都是基于 Element
对象的 API 实现。
在爬虫代码采集过程中,通过 etree.HTML
直接将字符串实例化为 element
对象。
- import requests
- from lxml import etree
-
- res = requests.get("http://www.jsons.cn/zt/")
-
- html = res.text
-
- root_element = etree.HTML(html)
-
- print(root_element)#<Element html at 0x3310508>
-
- print(root_element.tag)#html
其中需要注意的是 Element 后面的 html,该字符串表示对象的标签名为 html
,如果使用下述代码:
print(root_element[0])
上述内容得到的是 <Element head at 0x1913771e800>,即head标签,同样的操作可以使用子元素获取。
- print("*"*100)
- for child in root_element:
- print(child.tag)#head 表示在 html 标签中,只包含head 标签
也可以通过 etree.tostring(element对象)
直接将该对象转换为字符串进行输出。
- for child in root_element:
- for item in child:
- print(item.tag)
- print(etree.tostring(item))
lxml 库可以配合其他的解析引擎进行工作,首次接触的就是 XPath
,
在爬虫代码编写中,直接使用 html.xpath("xpath表达式")
即可获取目标数据,例如获取网页 title。
print(root_element.xpath('//title'))
获取网页所有文本:
print(root_element.xpath('string()'))
获取到 element 对象之后,可调用 text
属性,获取对应文本,在使用的时候,需要注意使用 XPath
获取到的 element 对象,都是列表。
- title_element = root_element.xpath('//title')
- print(title_element[0].text)
在 lxml
中,还内置了一款 简单的类似 XPath 的路径语言,称为 ElementPath
,例如查询 title,需要从 head
开始检索,否则返回 None
。
print(root_element[0].find("title"))
官方提供的方法如下:
iterfind()
: 返回查找到的数据,迭代器形式返回;findall()
: 返回匹配到的列表;find()
: 返回第一个匹配到的数据;findtext()
: 返回匹配到的文本数据,第一个。正则表达式 与 XPath 语法领域细解,初学阶段的你,该怎么学?
lxml
除了可以配合 XPath
实现数据解析外,还可以与 cssselect
,BeautifulSoup
,html5lib
配合使用,这部分在后续的案例中,将逐步进行展开。
lxml
在爬虫领域,更多的是在提取数据,因此较于该库本身,掌握 XPath
等解析表达式的写法更加重要。
Python 爬虫或网络请求时,最先接触的第三方库就是 requests
,requests
库提供了中文手册 - https://docs.python-requests.org/zh_CN/latest/
。
requests.get()
方法除 url 参数外,其余都为可选参数,即非必选。
url
:请求地址;params
:要发送的查询字符串,可以为字典,列表,元组,字节;data
:body 对象中要传递的参数,可以为字段,列表,元组,字节或者文件对象;json
:JSON 序列化对象;headers
:请求头,字典格式;cookies
:传递 cookie,字段或 CookieJar
类型;files
:最复杂的一个参数,一般出现在 POST
请求中,格式举例 "name":文件对象
或者 {'name':文件对象}
,还可以在一个请求中发送多个文件,不过一般爬虫场景不会用到;auth
:指定身份验证机制;timeout
:服务器等待响应时间,在源码中检索到可以为元组类型,这个之前没有使用过,即 (connect timeout, read timeout)
;allow_redirects
:是否允许重定向;proxies
:代理;verify
:SSL 验证;stream
:流式请求,主要对接流式 API;cert
:证书。除了 GET
请求外,requests
还内置了其他的服务器请求方式GET
, OPTIONS
, HEAD
, POST
, PUT
, PATCH
, DELETE
这些方法需要的参数与上述清单一致。
在 Python 爬虫的实战当中,主要以 GET
与 POST
为主,
常用的参数为:url
,params
,data
,headers
,cookies
,timeout
,proxies
,verify
。
使用 requests
库请求之后,会得到一个 Response
对象,掌握该对象的技巧就是了解其属性与方法,通过 dir()
函数可以获取 Response
对象的属性和方法。
- help(res)
- print(dir(res))
获取到的内容如下所示,其中有我们之前案例中常见的一些内容。
['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '其余内容自行查询']
如果只将 requests
库应用在爬虫采集领域,那上述属性与方法中,比较常用的有:
属性 property
ok
:只要状态码 status_code
小于 400,都会返回 True;is_redirect
:重定向属性;content
:响应内容,字节类型;text
:响应内容,Unicode 类型;status_code
:响应状态码;url
:响应的最终 URL 位置;encoding
:当访问 r.text
时的编码;方法
json()
:将响应结果序列化为 JSON; requests 存在的
高级特性,即会话对象,会话对象可以保持参数。
该对象能够在跨域请求的时候,保持住某些参数,尤其是 cookie
,如果你想向同一主机发送多个请求,使用会话对象可以将底层的 TCP 连接进行重用,从而带来显著的性能提升。
会话对象使用非常简单,在发起 requests
对象之前,增加如下所示代码即可。
- # 建立会话对象
- s = requests.Session()
- # 后续都使用会话对象进行进行,而不是直接使用 requests 对象
- s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
- r = s.get("http://httpbin.org/cookies")
- print(r.text)
会话也可用来为请求方法提供缺省数据,顾名思义就是直接给会话对象增加的请求参数,
- import requests
- s = requests.Session()
- s.auth = ('user', 'pass')
- s.headers.update({'x-test': 'true'})
-
- # both 'x-test' and 'x-test2' are sent
- r = s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
-
- print(r.text)
方法级别的参数也不会被跨请求保持,即在 s.get()
方法中如果传递了 cookie
,那不会被保持住。
通过会话对象的属性设置的参数,能被保持,而通过会话对象方法传递的参数,不能被保持。
在爬虫采集数据的过程中,碰到 https
的网站在正常不过,requests
库使用过程中 SSL 验证是默认开启的,如果证书验证失败,即抛出 SSLError
错误。
不过在实战的时候,我们可以通过设置 verify = False
,忽略对 SSL 证书的验证。
部分场景无法忽略证书,必须增加相关证书逻辑。
有的网站在采集过程中,会针对 IP 进行限制,此时就需要使用代理进行跳过操作,设置 proxies
参数即可,
除了 HTTP 代理外, requests 2.10
版本之后,增加了 SOCKS
代理,如果你需要使用,需要通过 pip
安装相应库。
pip install requests[socks]
安装完毕,出现新的第三方库 PySocks
,使用方式与 HTTP 代理一致。
爬虫采集过程会大量的与 cookie
打交道,获取网站响应的 cookie
,使用 response
对象的 cookies
属性即可。
如果希望向服务器传递 cookie
,可以通过 cookies
参数,例如下述代码:
- url = 'http://httpbin.org/cookies'
- cookies = dict(cookies_are='working')
- r = requests.get(url, cookies=cookies)
如果你希望对 cookie
有更加细致的操作,重点研究 requests.cookies.RequestsCookieJar
对象即可,
简单的代码使用如下所示:
- jar = requests.cookies.RequestsCookieJar()
- jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
- jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
- url = 'http://httpbin.org/cookies'
- r = requests.get(url, cookies=jar)
- print(r.text)
RequestsCookieJar
对象具备更加丰富的接口,适合跨域名跨路径使用,相关接口可在 https://docs.python-requests.org/zh_CN/latest/api.html#requests.cookies.RequestsCookieJar 查询。
requests
非常适合作为 Python 爬虫入门阶段第一选择,其简单的接口与代码封装,能大幅度降低网络请求代码编写难度,让你专注与目标数据的提取,更有基于高级请求的封装作为提高部分,该库完全可以贯穿你的整个爬虫工程师生涯。
学习基本使用之后,可以使用 requests
模块实现一些简易爬虫案例,例如参考《Python 爬虫小课》,全部都是基于 requests 模块完成。
requests
模块目前在 Python 爬虫领域的出场率极高,很多简单的接口开发,也会基于它进行实现,
因此,该模块十分重要,需要牢牢掌握
selenium 项目最早是为测试浏览器、网页开发的,并且广泛应用于爬虫,需要注意 selenium
不是单个软件,它其实由一系列的工具组成。
selenium 与 webdriver 是两个项目, webdriver 是对 selenium 的二次开发,selenium 存在三个大版本,关系如下所示:
selenium1.0 + webdriver = selenium2.0
使用命令 pip install selenium
即可安装 selenium
库,安装完毕直接通过 import selenium
测试即可。
接下来还需要下载一个 WebDriver
,它用于驱动浏览器运行。
chrome 浏览器 的 WebDriver(chromedriver.exe),可以在下述地址下载:
CNPM Binaries Mirror
firefox 浏览器的 WebDriver(geckodriver.exe),可以在下述地址下载:
https://github.com/mozilla/geckodriver/releases
其他浏览器驱动:
Edge:https://developer.microsoft.com/en-us/micrsosft-edage/tools/webdriver
Safari:WebDriver Support in Safari 10 | WebKit
一般使用 chrome 浏览器,在下载前,先查询本地 chrome 浏览器版本。
下载文件之后,解压到一个固定目录,记住该地址,需要在环境变量中进行配置。
G:\chromedriver_win32
测试配置是否正确:
- from selenium import webdriver
-
- driver = webdriver.Chrome()
运行代码出现谷歌浏览器,表示安装完成。
使用 selenium
打开百度首页。
- from selenium import webdriver
-
- driver = webdriver.Chrome()
-
- # 设置浏览器大小
- driver.set_window_size(800,600)
- # 可以直接最大化
- driver.maximize_window()
-
- # 打开百度
- driver.get("http://www.baidu.com")
基本操作包括:
- from selenium import webdriver
- import time
-
- driver = webdriver.Chrome()
-
- driver.maximize_window() # 最大化浏览器窗口
-
- driver.get("http://www.baidu.com") # 打开百度
-
- time.sleep(1) # 暂停1秒钟
- driver.get("https://www.csdn.net/") # 打开 CSDN 首页
-
- time.sleep(1) # 暂停1秒钟
- driver.back() # 回退
-
- time.sleep(1) # 暂停1秒钟
- driver.forward() # 前进
-
- time.sleep(1) # 暂停1秒钟
- driver.refresh() # 页面刷新
-
- time.sleep(1) # 暂停1秒钟
- driver.quit() # 浏览器关闭
元素定位需要 HTML 基础支持,这部分内容直接百度学习即可,selenium 提供了 8 种网页元素定位方式,分别如下:
find_element_by_id()
和 find_elements_by_id()
;find_element_by_class_name()
和 find_elements_by_class_name()
;find_element_by_tag_name()
和 find_elements_by_tag_name()
;find_element_by_css_selector()
和 find_elements_by_css_selector()
;find_element_by_name()
和 find_elements_by_name()
;find_element_by_xpath()
和 find_elements_by_xpath()
;find_element_by_link_text()
和 find_elements_by_link_text()
;find_element_by_partial_link_text()
和 find_elements_by_partial_link_text()
。其中返回
element
表示单数(第一个),返回elements
表示复数,得到全部。
接下来用 简书 jianshu.com 首页,完成定位测试。
- from selenium import webdriver
-
- driver = webdriver.Chrome()
-
- driver.maximize_window() # 最大化浏览器窗口
-
- driver.get("http://www.jianshu.com") # 打开简书
-
- driver.find_element_by_id("q").send_keys("梦想橡皮擦") # 通过ID检索搜索框,并输入文本
- driver.find_element_by_class_name("search-btn").click() # 通过 class name 搜索按钮,并点击
这里调用方法出现了一个问题,解决方式如下:
关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题
代码中的
send_keys()
表示想目标元素输入数据,click()
表示点击操作查看元素各种属性依赖浏览器的开发者工具,这些都属于前端知识,大家可以针对性的补充。
XPath 定位重点要学习的是 XPath 语句的写法,可以参考:正则表达式 与 XPath 语法领域细解,初学阶段的你,该怎么学?_梦想橡皮擦的博客-CSDN博客_xpath和正则表达式 进行学习。
通过 class(类)名进行定位
注意该定位方式不支持复合类名,例如 <ul class="nav navbar-nav"></i>
,无法使用 driver.find_element_by_class_name("nav navbar-nav")
进行获取,仅支持单独的 class
名称。
其余获取元素的方式基本雷同,一般情况下使用 ID 和 class(类)名获取元素场景比较多。
仅作为扩展知识,最新版本的 selenium 已经不支持 PhanomJS
PhanomJS 是一款隐形浏览器(无界面 / 无头浏览器),主要用于自动化测试,网络爬虫,网络监控等领域。
下载与安装非常简单,打开国内镜像网站下载即可,一般不要下载 beta 版本。
https://npm.taobao.org/mirrors/phantomjs
解压文件,获取 bin 目录完整路径,填写到环境变量中。
配置完毕,在控制台输入 phantomjs -v
查看程序对应版本。
由于谷歌和火狐浏览器都推出了无头浏览器,所以 selenium 弃用了 PhantomJS,使用 Chrome 无头浏览器的方式为:
- from selenium import webdriver
-
- opt = webdriver.ChromeOptions() # 创建 chrome 参数对象
-
- opt.headless = True # 设置无头浏览器
-
- driver = webdriver.Chrome(options=opt) # 创建 chrome 无界面对象
-
- driver.get("http://www.jianshu.com") # 打开简书
-
- title = driver.title
- print("网页标题是:", title)
-
- driver.save_screenshot("./jianshu.png")#保存截图
有的博客在设置无头浏览器时,会使用如下函数:opt.set_headless()
,不过在最新版本中也已经被废弃,使用 opt.headless
即可。
还可以编写如下代码:
- from selenium import webdriver
- from selenium.webdriver.chrome.options import Options
-
- opt = Options() # 创建 chrome 参数对象
- opt.add_argument('-headless') # 无头参数
-
- driver = webdriver.Chrome(options=opt) # 创建 chrome 无界面对象
-
- driver.get("http://www.jianshu.com") # 打开简书
-
- title = driver.title
- print("网页标题是:", title)
-
- driver.save_screenshot("./jianshu.png")
selenium 退出有两种方式:
driver.close()
:不会清除临时文件夹中的 WebDriver 临时文件;driver.quit()
:删除临时文件夹。表象的理解 close
与 quit
的区别是,close
关闭浏览器当前标签,quit
关闭浏览器。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。