老铁们,大家好,相信还有很多朋友对于深入解析:Python网络爬虫核心库与应用技巧和的相关问题不太懂,没关系,今天就由我来为大家分享分享深入解析:Python网络爬虫核心库与应用技巧以及的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!
文件读写方式:
r: 打开一个只有可读权限的文件
rb: 以二进制形式打开具有可读权限的文件
r+: 打开一个具有读写权限的文件
rb+: 以二进制形式打开一个文件,具有读写权限
w: 打开一个具有写权限的文件
wb: 以二进制形式打开具有写权限的文件
w+: 打开一个具有读写权限的文件
wb+: 打开一个具有读写权限的二进制形式的文件
a: 打开具有附加权限的文件
ab: 以二进制形式打开具有附加权限的文件
a+: 打开一个具有读写权限的文件
ab+: 以二进制形式打开一个具有读写权限的文件
获取响应的状态码:
XXXX.状态
获取响应的响应头:
XXXX.getheaders()
获取某个响应头参数
XXXX.getheader("参数名称")
获取当前请求的url地址
XXXX.url
获取请求原因(如果成功返回OK)
XXXX.原因
注意:response.read()只能读取一次
headers={}: 设置请求头并传递字段类型参数
我们首先看一下Urllib库,它是Python内置的HTTP请求库,这意味着我们不需要额外安装就可以使用它。它包含四个模块:
第一个模块request是最基本的HTTP请求模块。我们可以用它来模拟发送请求,就像在浏览器中输入URL 并按Enter 一样。我们只需要将URL 传递给库方法即可。通过附加参数,可以模拟该过程。第二个错误模块是异常处理模块。如果出现请求错误,我们可以捕获这些异常,然后执行重试或者其他操作,以保证程序不会意外终止。第三个parse模块是一个工具模块,提供了很多URL处理方法,比如分割、解析、合并等。第四个模块是robotparser,主要用于识别网站的robots.txt文件,然后判断是哪个哪些网站可以抓取,哪些网站不能抓取。实际上不太实用。
这里我们重点关注前三个模块。
一、发送请求
使用Urllib的请求模块我们可以轻松发送请求并获取响应
1、urlopen()
urllib.request 模块提供了构建HTTP 请求的最基本方法。它可以用来模拟浏览器发起请求的过程。它还处理authentication(授权验证)、redirections(重定向)、cookie(Browser Cookies)等内容。
让我们感受一下它的力量。以Python官网为例,我们抓取这个网页:
导入urllib.request
响应=urllib.request.urlopen("https://www.python.org")
print(response.read().decode("utf-8")) 结果如下:
接下来我们看一下它返回的内容,并使用type() 方法输出Response 的类型。
导入urllib.request
响应=urllib.request.urlopen("https://www.python.org")
print(type(response))的输出结果如下:
通过输出结果可以发现是一个HTTPResposne类型的对象。主要包含read()、readinto()、getheader(name)、getheaders()、fileno()等方法以及msg、version、status、reason、debuglevel、close等属性。
得到这个对象后,我们将其赋值给response变量,然后我们就可以调用这些方法和属性来获取返回结果的一系列信息。 +
例如,调用read()方法可以获取返回的网页内容,调用status属性可以获取返回结果的状态码。例如200表示请求成功,404表示未找到网页等。
我们再举个例子来感受一下:
导入urllib.request
响应=urllib.request.urlopen("https://www.python.org")
打印(响应.状态)
打印(响应.getheaders())
print(response.getheader("Server")) 的结果如下:
200
[("服务器", "nginx"), ("内容类型", "text/html; charset=utf-8"), ("X-Frame-Options", "SAMEORIGIN"), ("X-Clacks -Overhead", "GNU Terry Pratchett"), ("Content-Length", "47397"), ("Accept-Ranges", "bytes"), ("日期", "Mon, 01 Aug 2016 09:57:31 GMT") , ("Via", "1.1 清漆"), ("年龄", "2473"), ("连接", "关闭"), ("X-Served-By", "cache-lcy1125-LCY"), ("X-Cache", "HIT"), ("X-Cache-Hits", "23"), ("Vary", "Cookie"), ("严格传输安全", "max-age=63072000;包括子域")]
从nginx可以看出,三个输出分别输出了响应的状态码、响应的头信息,而headers中的Server值是通过调用getheader()方法并传递一个参数Server来获取的。结果是nginx,也就是说服务器是用nginx搭建的。
利用上面最基本的urlopen()方法,我们就可以完成简单网页的最基本的GET请求爬取。
如果我们想向链接传递一些参数怎么办?我们首先看一下urlopen()函数的API:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None) 可以发现除了第一个可以传递URL的参数之外,我们还可以传递其他内容,比如data(附加数据)、timeout(超时时间)等。
下面我们详细解释一下:这几个参数的用法
data参数
数据参数是可选的。如果要添加数据,必须是字节流编码格式,即bytes类型,可以通过bytes()方法进行转换。另外,如果传递了这个数据参数,那么它的请求方法就不再是GET请求,而是POST请求。
我们用一个例子来感受一下:
导入urllib.parse
导入urllib.request
数据=bytes(urllib.parse.urlencode({"word": "hello"}), 编码="utf8")
响应=urllib.request.urlopen("http://httpbin.org/post", data=data)
print(response.read()) 这里我们传递一个参数word,值为hello。需要转码为bytes(字节流)类型。 bytes()方法用于转换字节流。第一个参数需要是str(字符串)类型,需要使用urllib.parse模块中的urlencode()方法将参数字典转换为字符串。第二个参数指定编码格式,这里指定为utf8。
timeout参数
timeout参数可以设置超时时间,单位是秒,也就是说如果请求超过设置的时间还没有收到响应,就会抛出异常。如果未指定,将使用全局默认时间。它支持HTTP、HTTPS、FTP 请求。
因此,我们可以设置这个超时时间来控制网页如果长时间没有响应则跳过抓取。这个操作可以通过使用try except语句来实现。代码如下:
进口插座
导入urllib.request
导入urllib.error
尝试:
响应=urllib.request.urlopen("http://httpbin.org/get", timeout=0.1)
除了urllib.error.URLError 为e:
if isinstance(e.reason, socket.timeout):
print("TIME OUT")
其他参数
还有一个上下文参数,该参数必须是ssl.SSLContext 类型才能指定SSL 设置。
cafile和capath这两个参数指定CA证书及其路径,这在请求HTTPS链接时很有用。
cadefault 参数现已弃用,默认为False。
上面解释了urlopen()方法的用法。通过这个最基本的功能就可以完成简单的请求和网页爬取。更详细的信息可以参考官方文档:https://docs.python.org/3/library/urllib.request.html。
2、Request
从上面我们知道,urlopen()方法可以用来发起最基本的请求,但是这些简单的参数不足以构造一个完整的请求。如果请求中需要添加headers 等信息,我们可以使用更强大的Request 类来构造请求。
首先我们通过一个例子来体验一下Request的使用:
导入urllib.request
request=urllib.request.Request("https://python.org")
响应=urllib.request.urlopen(请求)
print(response.read().decode("utf-8")) 可以发现我们仍然使用urlopen()方法来发送本次请求,只不过这次urlopen()方法的参数不再是URL ,但是它是一个Request类型的对象。通过构建这个数据结构,一方面我们可以将请求分离成一个对象,另一方面可配置的参数更加丰富和灵活。
我们看一下Request可以通过哪些参数来构造。其施工方法如下:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverABLE=False, method=None) 第一个url 参数是请求URL。这是必需的参数,其他参数是可选的。选择参数。
如果要传递第二个数据参数,则必须是bytes(字节流)类型。如果是字典,可以先使用urllib.parse模块中的urlencode()对其进行编码。
第三个headers参数是一个字典,即Request Headers。可以在构造Request时直接通过headers参数来构造,也可以通过调用Request实例的add_header()方法来添加。请求标头最常见的用法是修改它。 User-Agent 用于伪装浏览器。默认的用户代理是Python-urllib。我们可以修改它来伪装浏览器。
第四个origin_req_host参数指请求者的主机名或IP地址。
第五个不可验证参数是指该请求是否无法验证。默认值为False。这意味着用户没有足够的权限来选择接收此请求的结果。例如,我们请求HTML文档中的图像,但我们没有自动捕获图像的权限。在这种情况下,无法验证的值为True。
第六个method参数是一个字符串,表示请求使用的方法,例如GET、POST、PUT等。
写一个例子:
从urllib 导入请求,解析
url="http://httpbin.org/post"
标题={
"用户代理": "Mozilla/4.0(兼容;MSIE 5.5;Windows NT)",
"主机": "httpbin.org"
}
字典={
"名称": "德国"
}
数据=字节(parse.urlencode(dict), 编码="utf8")
req=request.Request(url=url, data=data, headers=headers, method="POST")
响应=request.urlopen(req)
print(response.read().decode("utf-8")) 这里我们构造一个带有四个参数的Request。 url 是请求的URL。用户代理和主机在标头中指定。传递的参数数据为urlencode() 和bytes() 方法将其转换为字节流,请求方式指定为POST。
通过观察结果,我们可以看到我们成功设置了数据、头和方法。
此外,还可以使用add_header() 方法添加标头。
req=request.Request(url=url, data=data, method="POST")
req.add_header("User-Agent", "Mozilla/4.0 (兼容; MSIE 5.5; Windows NT)") 这样我们就可以更方便的构造一个Request并发送请求。
二、 处理异常
我们了解了Request的发送流程,但是当网络状况不好的时候出现异常怎么办?如果我们此时不处理这些异常,程序很可能会报错并终止运行,所以异常处理还是非常有必要的。 +
Urllib的错误模块定义了请求模块生成的异常。如果出现问题,请求模块将抛出错误模块中定义的异常。
主要有两个异常处理类,URLError和HTTPError。
下面写一个例子:
从urllib 导入请求,错误
尝试:
response=request.urlopen("http://cuiqingcai.com/index.htm")
除了error.URLError 为e:
print(e.reason) 我们打开一个不存在的页面。按理说应该报错,但是此时我们捕获了URLError异常,运行结果如下:
未找到urllib 导入请求,错误
尝试:
response=request.urlopen("http://cuiqingcai.com/index.htm")
除了错误。HTTPError 为e:
print(e.reason, e.code, e.headers, seq="n") 结果:
未找到
404
服务器: nginx/1.4.6 (Ubuntu)
日期: 2016 年8 月3 日星期三08:54:22 GMT
内容类型:文本/html;字符集=UTF-8
Transfer-Encoding: 分块
连接:关闭
X-Powered-By: PHP/5.5.9-1ubuntu4.14
Vary: 饼干
过期时间: 1984 年1 月11 日星期三05:00:00 GMT
Cache-Control: 无缓存,必须重新验证,max-age=0
Pragma: 无缓存
链接: rel="https://api.w.org/"HTTPError,它有三个属性。
code,返回HTTP Status Code,即状态码,如404网页不存在、500服务器内部错误等。reason与父类一样,返回错误原因。 headers,返回请求标头。
因为URLError是HTTPError的父类,所以我们可以选择先捕获子类的错误,然后再捕获父类的错误。因此,上述代码更好的写法如下:from urllib import request,报错
尝试:
response=request.urlopen("http://cuiqingcai.com/index.htm")
除了错误。HTTPError 为e:
print(e.reason, e.code, e.headers, sep="n")
除了error.URLError 为e:
打印(e.原因)
否则:
print("请求成功") 这样我们就可以先捕获HTTPError并获取其错误状态码、原因、标题等详细信息。如果不是HTTPError,则捕获URLError异常并输出错误原因。最后,使用else来处理正常逻辑,这是编写异常处理的更好方法。
requests
requests是基于urllib的另一种封装。它具有urllib的所有功能,API调用更加方便。它是一个基于网络请求的模块,模拟浏览器发起请求。
为什么使用请求模块?
1.自动处理url编码
2.自动处理post请求参数
3. 简化cookie和代理操作
Cookie 操作:
一个。创建cookiejar 对象
b.创建处理程序对象
c.创建一个开启对象
代理经营:
一个。创建一个handler对象,并将代理IP和端口封装到该对象中
b.创建开启对象
安装:pip3安装请求
使用流程:
1.指定网址
2.使用requests模块发起请求
3.获取响应的二进制数据
4. 进行持久化存储
请求包括五种请求类型:get、post、ajax get请求、ajax post请求、综合
导入请求
1、指定url
url="https://www.sogou.com/"
2、发起get请求:get方法会返回请求成功的相应对象
响应=requests.get(url=url)
3、获取响应中的数据值:text可以获取响应对象中字符串形式的页面数据
page_data=响应.text
打印(页面数据)
4、持久化操作
with open("./sougou.html","w",encoding="utf-8") as fp:
fp.write(page_data)
requests 对象中的其他重要属性:
text 可以在response对象中以字符串的形式获取页面数据
content获取的是响应对象中的二进制(字节)页面数据。
response.status 返回响应状态代码
response.headers 返回响应头信息
自定义请求头信息:
从fake_useragent 导入UserAgent
自定义请求标头
标题={
"用户代理":UserAgent().random
}
封装get请求参数:
参数={
"变量名":"参数"
}
使用requests发起post请求
导入请求
从fake_useragent 导入UserAgent
def 登录():
1、指定POST请求的URL
url="https://accounts.douban.com/j/mobile/login/basic"
封装post请求的参数
数据={
"ck":"",
"姓名": "16619983290",
"密码": "wwy123456",
"记住": "假",
"票":""
}
标题={
"用户代理": UserAgent().random
}
2、发起POST请求
响应=requests.post(url=url, data=data, headers=headers)
3、获取响应回来的信息
打印(响应.文本)
requests库中session的作用:
维护统一的会话,跨请求访问时保存一些信息(如cookie)
cookie:
1、基于用户的用户数据
2、需求:爬取用户xx的豆瓣个人主页数据
Cookie功能:服务器使用cookie来记录客户端状态信息
实施过程:
1.执行登录操作(获取cookie)
2、发起个人主页请求时,需要在请求中携带cookie。
注:session对象:发送请求(cookie对象会自动存储)
正则
单字符匹配。除换行符之外的任何字符
d 代表一个数字
D 匹配非数字
w 匹配单词字符[a-z,A-Z,0-9]
W 匹配非单词字符
s 匹配空白字符、空格、n t.
S 匹配非空白字符
^ 以.开头的匹配
$ 匹配结尾为
[0-9]=d 匹配0-9
多字符匹配(贪心匹配)
匹配* 前面的字符任意次匹配+ 前面的字符至少一次
?匹配?前面的字符0-1次
{n,m} 匹配{n,m} 之前的字符n-m 次多字符匹配(非贪婪匹配)
*?
+?
?
其他
() 分组
|逻辑或
转义字符
re模块下的方法
re.compile():构建正则表达式对象
re.match(): 从起始位置开始匹配,单次匹配,如果匹配到则立即返回,否则返回None
re.search(): 整个字符串匹配,单次匹配,如果匹配到则立即返回,否则返回None
re.findall(): 匹配整个字符串中所有符合正则规则的结果,并返回一个列表
re.finditer(): 匹配整个字符串中所有符合正则规则的结果,并返回一个可迭代对象
re.sub():基于正则表达式的字符串替换
re.split(): 根据正则表达式分割
xpath
安装:pip install lxml
引用: from lxml import etree
创建etree对象,用于指定的数据分析
1. 本地
etree=etree.parse("本地路径")
etree.xpath("xpath表达式")
2.网络
etree=etree.HTML("网络请求页面数据")
etree.xpath("xpath表达式")
常用的xpath表达式:
1.属性定位:
找到class属性值为song的div标签
//div[@class="歌曲"]
2.分层索引定位
找到class属性值为tang的div的直接子标签ul的第二个子标签li下的直接子标签a。
//div[@class="tang"]/ul/li[2]/a
3. 逻辑运算
找到href属性值为空、class属性值为du的a标签
//a[@href="" 和@class="du"]
4. 模糊匹配
/表示获取某个标签下的文本内容//div[@class="song"]/p[1]/text()
//表示获取某个标签下的文本内容以及所有子标签下的文本内容//div[@class="tang"]//text()
5. 获取属性
//div[@class="tang"]//li[2]/a/@href
bs4(python独有简单便捷和高效)
环境安装:pip install lxml bs4使用lxml库。如果尚未安装lxml库,则需要安装它。
代码使用流程:
核心思想:可以将html文档转换为BeautifulSoup对象,并可以调用该对象中的属性和方法。
【深入解析:Python网络爬虫核心库与应用技巧】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
学习爬虫网站感觉这些工具都很有用!
有9位网友表示赞同!
我想用 urllib 下载网页内容,然后使用正则表达式提取一些信息。
有18位网友表示赞同!
我正在尝试学习 Python 用 bs4 解析 HTML 文件,挺复杂的啊!
有11位网友表示赞同!
xpath 可以很方便地定位到网页上的特定元素吧?
有13位网友表示赞同!
感觉 urllib 和 request 可以用来下载很多不同类型的文件吧?
有18位网友表示赞同!
爬虫入门还是比较困难的吗?感觉这些工具需要慢慢学习。
有13位网友表示赞同!
正则表达式太强大了吧,可以提取很多复杂的信息!
有17位网友表示赞同!
想用 bs4 生成一个漂亮的网页展示数据,不知道怎么做呢?
有20位网友表示赞同!
xpath 和 bs4 都是用来解析 HTML 的吧?有什么区别吗?
有11位网友表示赞同!
学习爬虫网站,感觉 urllib 和 request 是基础知识了。
有13位网友表示赞同!
正则表达式看起来很复杂,但是实际使用起来很有用!
有16位网友表示赞同!
bs4 可以处理多种格式的文档吗?比如 XML 文件?
有10位网友表示赞同!
我尝试过用 bs4 解析网页,但是有时候会遇到解析错误怎么办?
有6位网友表示赞同!
xpath 比 正则表达式更灵活吗?
有12位网友表示赞同!
学习爬虫网站的目的是什么?有什么实际用途吗?
有5位网友表示赞同!
bs4 可以用来抓取网页图片或视频文件吗?
有14位网友表示赞同!
urllib 的使用范围比较广吧?
有15位网友表示赞同!
想了解一下如何使用XPATH 和 Regular Expression 进行数据提取和分析。
有17位网友表示赞同!
bs4 和 其他类似的解析HTML的库有什么区别呢?
有6位网友表示赞同!
学习完这些工具以后,我可以自己开发爬虫程序吗?
有8位网友表示赞同!