type
status
date
slug
summary
tags
category
icon
password
Property
urllib
urllib
提供了一系列用于操作URL的功能Get
rllib
的request
模块可以非常方便地抓取URL内容,也就是发送一个GET请求到指定的页面,然后返回HTTP的响应:例如,对豆瓣的一个URL
https://api.douban.com/v2/book/2129650
进行抓取,并返回响应:可以看到HTTP响应的头和JSON数据:
如果要想模拟浏览器发送GET请求,就需要使用
Request
对象,通过往Request
对象添加HTTP头,就可以把请求伪装成浏览器。例如,模拟iPhone 6去请求豆瓣首页:这样豆瓣会返回适合iPhone的移动版网页:
Post
如果要以
POST
发送一个请求,只需要把参数data
以bytes形式传入。模拟一个微博登录,先读取登录的邮箱和口令,然后按照
weibo.cn
的登录页的格式以username=xxx&password=xxx
的编码传入:如果登录成功,获得的响应如下:
如果登录失败,获得的响应如下:
Handler
如果还需要更复杂的控制,比如通过一个
Proxy
去访问网站,需要利用ProxyHandler
来处理:XML
操作XML有两种方法:DOM和SAX。DOM会把整个XML读入内存,解析为树,因此占用内存大,解析慢,优点是可以任意遍历树的节点。SAX是流模式,边读边解析,占用内存小,解析快,缺点是需要自己处理事件。
正常情况下,优先考虑SAX,因为DOM实在太占内存。
在
Python
中使用SAX
解析XML
非常简洁,通常关心的事件是start_element
,end_element
和char_data
,准备好这3个函数,然后就可以解析xml
了。举个例子,当SAX解析器读到一个节点时:
<a href="/">python</a>
,会产生3个事件:start_element
事件,在读取<a href="/">
时
char_data
事件,在读取python
时
end_element
事件,在读取</a>
时
需要注意的是读取一大段字符串时,
CharacterDataHandler
可能被多次调用,所以需要自己保存起来,在EndElementHandler
里面再合并。除了解析
XML
外,如何生成XML
呢?99%的情况下需要生成的XML
结构都是非常简单的,因此,最简单也是最有效的生成XML的方法是拼接字符串:如果要生成复杂的XML呢?建议不要用XML,改成JSON
HTMLParser
如果要编写一个搜索引擎,第一步是用爬虫把目标网站的页面抓下来,第二步就是解析该HTML页面,看看里面的内容到底是新闻、图片还是视频。
假设第一步已经完成了,第二步应该如何解析
HTML
呢?HTML
本质上是XML
的子集,但是HTML
的语法没有XML
那么严格,所以不能用标准的DOM
或SAX
来解析HTML
。好在
Python
提供了HTMLParser
来非常方便地解析HTML
,只需简单几行代码:feed()
方法可以多次调用,也就是不一定一次把整个HTML
字符串都塞进去,可以一部分一部分塞进去。特殊字符有两种,一种是英文表示的
,一种是数字表示的Ӓ
,这两种字符都可以通过Parser
解析出来。requests(第三方库)
要通过
GET
访问一个页面,只需要几行代码:对于带参数的URL,传入一个
dict
作为params
参数:requests
自动检测编码,可以使用encoding
属性查看:r.encoding
无论响应是文本还是二进制内容,都可以用
content
属性获得bytes
对象:r.content
requests
的方便之处还在于,对于特定类型的响应,例如JSON,可以直接获取:需要传入HTTP Header时,传入一个
dict
作为headers
参数:要发送
POST
请求,只需要把get()
方法变成post()
,然后传入data
参数作为POST请求的数据:requests
默认使用application/x-www-form-urlencoded
对POST数据编码。如果要传递JSON数据,可以直接传入json参数:类似的,上传文件需要更复杂的编码格式,但是
requests
把它简化成files
参数:在读取文件时,注意务必使用
'rb'
即二进制模式读取,这样获取的bytes
长度才是文件的长度。把
post()
方法替换为put()
,delete()
等,就可以以PUT或DELETE方式请求资源。除了能轻松获取响应内容外,
requests
对获取HTTP响应的其他信息也非常简单。例如,获取响应头:requests
对Cookie
做了特殊处理,不必解析Cookie
就可以轻松获取指定的Cookie:r.cookies['ts']
要在请求中传
入Cookie
,只需准备一个dict传入cookies
参数:最后,要指定超时,传入以秒为单位的
timeout
参数: