爬虫阶段总结
Posted jianwei_S
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爬虫阶段总结相关的知识,希望对你有一定的参考价值。
获取数据
requests
-
步骤
-
引入模块
import requests
-
请求网络数据
response = requests.get('目标网页')
-
设置解码方式
response.encoding = 'utf-8'
-
获取请求结果
# 获取请求结果的文本数据 response.text # 获取二进制格式的请求结果(图片,视频,音频) response.content # 下载图片 response = requests.get('图片地址') result = response.content # 将数据保存到文件里 with open('files/a.jpg', 'wb') as f: f.write(result) # 获取请求结果json转换的结果 response.json()
-
浏览器伪装
header = 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/111.0.0.0 Safari/537.36' response = requests.get('目标网页',headers = header)
-
登录反爬
检查->network->all->找到网页请求->复制cookie的值
header = 'user-agent': 'user-agent的值', 'cookie':'cookie的值' response = requests.get('目标网页',headers = header)
-
代理ip
# 给proxies赋值 proxoes = 'https': '180.105.81.232:4515' response = requests.get('https://www.zhihu.com', headers=header, proxies=proxoes)
-
selenium
-
基础语法
from selenium.webdriver import Chrome # 创建浏览器对象 b = Chrome() # 打开网页 b.get('https://cd.zu.ke.com/zufang/pg2/#contentList') # 获取网页源代码 print(b.page_source)
- 利用循环获取多个网页内容
from selenium.webdriver import Chrome # 创建浏览器对象 b = Chrome() # 找到多页规律利用循环获取多页内容 for x in range(0, 100): b.get(f'https://cd.zu.ke.com/zufang/pgx/#contentList') print(b.page_source)
- 点击翻页按钮,再刷新后获取网页源代码
# 点击翻页按钮,再刷新后获取网页源代码 b = Chrome() b.get(f'https://cd.zu.ke.com/zufang/#contentList') for _ in range(5): b.page_source # 点击下一页按钮 # 通过class属性名获取标签 c = b.find_element(By.CLASS_NAME,'next') c.click()
- 输入框输入内容
from selenium.webdriver import Chrome from selenium.webdriver.common.by import By # 创建浏览器对象 b = Chrome() # 打开网页 b.get('https://www.cnki.net/') # 获取输入框对象 input_ = b.find_element(By.ID, 'txt_SearchText') # 输入框输入文字 input_.send_keys('数据分析\\n')
- 点击标签-
标签.click()
# 获取点击对象 title = b.find_elements(By.CLASS_NAME, 'fz14') for x in range(20): # 点击 title[x].click()
- 切换标签页
# 切换到最新的标签页 b.switch_to.window(b.window_handles[-1]) # 关闭标签页 b.close() # 返回第一个标签页 b.switch_to.window(b.window_handles[0])
- 鼠标滚动
from selenium.webdriver import Chrome import time b = Chrome() b.get('https://www.cnki.net/') # 单次滚动 b.execute_script('window.scrollBy(0,200)') # 多次滚动 for x in range(8): b.execute_script('window.scrollBy(0,200)') time.sleep(2)
-
selenium获取标签
-关键字 -含义 说明 By.ID 听过ID属性值获取标签 By.CLASS_NAME 通过class属性名获取标签 By.CSS_SELECTOR 通过css选择器获取标签 By.LINK_TEXT 通过a标签的标签内容获取标签 只有a标签有用,必须全部匹配 By.NAME 通过名字获 By.TAG_NAME By.PARTIAL_LINK_TEXT 获取包含str的a标签 部分匹配 By.XPATH -
登录反爬
获取cookie
from selenium.webdriver import Chrome # 创建浏览器打开需要自动登录的网站 b = Chrome() b.get('https://www.taobao.com') # 留足够长的时间,人工完成登录(必须保证b指定的网址能看到登录成功以后的信息) input('是否一登录') # 获取登录成功之后的cookie信息保存到本地文件 result = b.get_cookies() with open('files/taobao.txt', 'w') as f: f.write(str(result))
使用cookie
from selenium.webdriver import Chrome # 创建浏览器打开需要自动登录的网站 b = Chrome() b.get('https://www.taobao.com') # 获取本地cookie文件里的cookie with open('files/taobao.txt','r') as f: result = eval(f.read()) # 添加cookie for item in result: b.add_cookie(item) # 重新打开网页 b.get('https://www.taobao.com') input('end')
-
代理ip
解析数据
正则
bs4
-
步骤
-
引入模块
from bs4 import BeautifulSoup
-
创建soup对象
f = open('files/data.html', encoding='utf-8') soup = BeautifulSoup(f.read(), 'lxml') f.close()
-
获取标签
# 获取整个网页中选择器选中的所有标签,返回值是一个列表,列表中的元素是标签对象(找不到返回空列表) soup对象.select(css选择器) # 获取整个网页中选择器选中的第一个标签,返回值是标签对象(找不到返回None) soup对象.select_one(css选择器) # 获取指定标签中css选择器选中的所有标签 标签对象.select(css选择器) # 获取指定标签中css选择器选中的第一个标签 标签对象.select_one(css选择器) result = soup.select('p')
-
获取标签内容和属性
# 获取标签内容 标签对象.text # 获取标签指定属性的值 标签对象.attrs[属性名] print(p1.text) # '我是段落5' print(a1.text) # '我是超链接3' print(a1.attrs['href'])
-
xpath
通过路径来获取标签
# 1.绝对路径: /开头,从根节点开始层层往下写路径
# 2.相对路径: ./..开头,从当前路径开始写 ..表示上层路径
# 3.全路径 : 以 // 开头的路径
html = open('files/data.html').read()
-
语法
-
引用
html = open('files/data.html').read() # 解析对象是html # 根据数据创建树结构 root1 = etree.HTML(html) # 解析对象是xml root1= etree.XML()
-
基础语法结构
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <p> <span>我是span1</span> <a href="">我是超连接1</a> </p> <p> <span>我是span2</span> <a href="">我是超连接2</a> </p> <a href="https://www.baidu.com">我是超链接2</a> <p>我是段落2</p> <a href="https://www.taobao.com">我是超链接4</a> <div> <div> <a href="">我超链接3</a> </div> <div> <p>我是段落3</p> </div> </div> </div> </body> </html>
节点对象.xpath() - 根据获取所有的标签,返回值是列表
- 相对路径
# 相对路径写法 - 用谁.xpath.就代表谁 root1.xpath('./body/div/p')
- 绝对路径
# 绝对路径写法 root1.xpath('/html/body') # 获取标签内容 root1.xpath('/html/body/div/p/text()') # 获取标签属性 root1.xpath('/html/body/div/p/@href')
- 全路径
root1.xpath('//div/p') # 找符合这个结构所有的a标签 # 获取标签内容 root1.xpath('//div/p/text()') # 获取标签属性 root1.xpath('//div/p/@href')
-
加谓语(条件)
-
位置相关谓语
[n]
# 符合条件的有多个,取第一个 root1.xpath('//div/p[1]/text()') # 取第二个 root1.xpath('//div/p[2]/text()') # 取最后一个 root1.xpath('//div/p[last()]/text()') # 获取位置大于n的数据 root1.xpath('//div/p[position()>n]/text()') # 获取倒数第二个 root1.xpath('//div/p[last()-1]/text()')
-
属性相关谓语
[@属性 = 属性值]
# 通过属性值对标签进行筛选 # [@属性 = 属性值] # 找到符合id为name且符合div/p结构的标签 root1.xpath('//div/p[@id = ’name‘]/text()') root1.xpath('//span[@class = "a2"]/*[@class = "c2"]/text()') root1.xpath('//span[2]/*[@class = "c2"]/text()')
-
-
通配符
在xpath中通过通配符表示任意标签和任意属性
# 表示获取div下所有id值为name的标签内容 root1.xpath('//div/*[@id = ’name‘]/text()') # 表示获取div下所有id值为name的标签所有属性 root1.xpath('//div/p[@id = ’name‘]/@*')
-
requests库与 lxml 库常用操作整理+总结,爬虫120例阶段整理篇
一路学习,一路总结,技术就是这样,应用之后,在进行整理,才可以加深印象。
本篇博客为小节篇,核心总结 requests 库与 lxml 库
文章目录
requests 库
在《爬虫 120 例》中,最先接触的第三方库就是 requests
,该库开源地址为:https://github.com/psf/requests
,官方的 solgan 为 Requests is a simple, yet elegant, HTTP library
。
日常在编码过程中,最重要的行为就是查询手册,requests
库提供了中文手册 - https://docs.python-requests.org/zh_CN/latest/
,大幅度降低了学习的难度。不过中文翻译夹带了不少翻译者的情绪化文字,阅读的时候忽略即可。
requests 库最常见的操作
由于该专栏前面已经对 requests
库进行了大量的使用,其常见操作我们也可以进行一些相应的总结了。
请求参数以及请求方法
导入 requests
库之后,基本都在围绕 requests.get
做文章,这里重点要回顾的是 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
请求中可以配置的参数,除了 GET
请求外,requests
还内置了其他的服务器请求方式,如下所示,这些方法需要的参数与上述清单一致。
GET
, OPTIONS
, HEAD
, POST
, PUT
, PATCH
, or 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__', '__doc__',
'__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__',
'__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__',
'__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'_content', '_content_consumed', '_next', 'apparent_encoding', 'close', 'connection',
'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect',
'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status',
'raw', 'reason', 'request', 'status_code', 'text', 'url']
如果只将 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
,那不会被保持住,这两个案例,从正面与反面为我们核心展示的就是,如何使用会话对象保持参数,通过会话对象的属性设置的参数,能被保持,而通过会话对象方法传递的参数,不能被保持。
SSL 证书验证,客户端证书,CA 证书
在爬虫采集数据的过程中,碰到 https
的网站在正常不过,requests
库使用过程中 SSL 验证是默认开启的,如果证书验证失败,即抛出 SSLError
错误。
不过更多的时候,我们通过设置 verify = False
,忽略对 SSL 证书的验证,除非及其特殊的情况,必须增加相关证书逻辑。
代理
有的网站在采集过程中,会针对 IP 进行限制,此时就需要使用代理进行跳过操作,设置 proxies
参数即可,本部分内容比较简单,后续很多案例还会复用到。
除了 HTTP 代理外, requests 2.10
版本之后,增加了 SOCKS
代理,如果你需要使用,需要通过 pip
安装相应库。
pip install requests[socks]
安装完毕,出现新的第三方库 PySocks
,使用方式与 HTTP 代理一致。
Cookie
爬虫采集过程会大量的与 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 爬虫入门阶段第一选择,其简单的接口与代码封装,能大幅度降低网络请求代码编写难度,让你专注与目标数据的提取,更有基于高级请求的封装作为提高部分,该库完全可以贯穿你的整个爬虫工程师生涯。
lxml 库
lxml
库是一款 Python 数据解析库,参考重要文档在 https://lxml.de/,项目开源地址在:https://github.com/lxml/lxml,在一顿检索之后,发现 lxml
没有中文相关手册,不过好在英文文档阅读难度不大,我们可以直接进行学习。
lxml.etree
纵览之前的博客内容,出场率最高的就是 lxml.etree
,其次就是 Element
对象,我们在解析数据的时候,大量的代码都是基于 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)
print(root_element.tag)
上述代码输出内容如下所示:
<Element html at 0x3310508>
html
其中需要注意的是 Element 后面的 html,该字符串表示对象的标签名为 html
,如果使用下述代码:
print(root_element[1])
上述内容得到的是 <Element body at 0x356e248>
,即 body 标签,同样的操作可以使用子元素获取。
print("*"*100)
for child in root_element:
print(child.tag)
上述代码输出的内容为:
head
body
该输出表示在 html
标签中,只包含head
与 body
标签,实际情况也确实如此,为了验证,你可以在 循环中继续嵌套一层。
此时输出的内容就变得丰富了需求,如下图所示:
你也可以通过 etree.tostring(element对象)
直接将该对象转换为字符串进行输出。
for child in root_element:
for item in child:
print(item.tag)
print(etree.tostring(item))
XPath
lxml 库可以配合其他的解析引擎进行工作,首次接触的就是 XPath
,关于 XPath 相关的知识,我们后续博客会细化学习,本节课依旧从 lxml
的角度出发,为你介绍。
在爬虫代码编写中,直接使用 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()
: 返回匹配到的文本数据,第一个。
lxml 其他说明
lxml
除了可以配合 XPath
实现数据解析外,还可以与 cssselect
,BeautifulSoup
,html5lib
配合使用,这部分在后续的案例中,将逐步进行展开。
lxml
在爬虫领域,更多的是在提取数据,因此较于该库本身,掌握 XPath
等解析表达式的写法更加重要。
鉴于该库手册没有被翻译,后期可以尝试将其翻译为中文。
收藏时间
爬虫120例代码下载地址:https://codechina.csdn.net/hihell/python120,可否给个 Star。
来都来了,不发个评论,点个赞,收个藏吗?
今天是持续写作的第 197 / 200 天。
可以关注我,点赞我、评论我、收藏我啦。
更多精彩
《Python 爬虫 100 例》只需要 39.9 元,即可享受 100+篇博客阅读权,每篇不到 4 毛钱。
以上是关于爬虫阶段总结的主要内容,如果未能解决你的问题,请参考以下文章