爬虫对于金融二级市场投资来说是重要的工具,可以帮助我们高效的提取数据,方便我们之后进行量化投资需要的图表生成,历史回测,信号发出等等工作。 底层数据的价值决定了策略的价值,这是我认为的数据对于量化投资的重要性。我认为使用市面上可以免费获得的数据库中的数据,并不会使得基本面量化策略的效果得到改善。数据挖掘,爬取数据,高效的处理数据应该是基本面量化策略的最基础的工作,也是任务量最大的工作。因此爬虫则显得尤为重要。
python爬虫 urllib库
urllib有4个模块,request(用来模拟发送请求,就像在浏览器中输入网址。);error(异常处理模块,用来捕获异常,防止程序终止);parse(提供了许多URL处理方法,拆分,解析,合并);robotparser(使用较少)。
1.发送请求
request模块提供了urlopen方法可以模拟浏览器的请求发起过程。
import urllib.request
response = urllib.request.urlopen("https://www.python.org")
print(response.read().decode("utf-8"))
print(type(response))
我们得到了网页的源代码,并且得到了一个HTTPResponse类型的对象,包括read(),readinto(),getheader(name),getheaders()等方法。以及msg,version,status,closed等属性。
import urllib.request
response = urllib.request.urlopen("http://www.python.org")
# 返回状态码,200代表成功
print(response.status)
# 会响应的头信息,并且可以获得指定参数的头信息。
print(response.getheaders())
print(response.getheader("Server"))
下面详细观察一下urlopen方法的参数设置
urllib.request.urlopen(url, data=None, [timeout,]*, cafile=None, capath=None, cadefault=False, context=None)
可以看见除了url地址以外我们还可以传递替他内容。
data参数:
import urllib.parse
import urllib.request
data = bytes(urllib.parse.urlencode({"word":"hello"}), encoding="utf-8")
response = urllib.request.urlopen("http://httpbin.org/post", data=data)
print(response.read())
data参数可以帮助我们模拟表单提交的方式,以POST方式传输数据。
timeout参数:如果请求超出了设置的时间,还没有得到响应,就会抛出异常。
其他参数:cafile和capath两个参数指定CA证书和它的路径。
2.request 发送请求
由于urlopen方法提供的参数较少,我们在发送请求的过程中需要传递比较多的参数信息。所以更多的时候我们是用Request类来构建。
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
第一个参数是url是必传参数,其他都是可选参数。第二个参数data参数,必须传bytes(字节流)类型的,可以用urllib.parse的urlencode()编码。第三参数headers是一个字典,也就是请求头。比较关键,往往我们第一次访问就被网站识别是爬虫的原因多半是我们没有设置headers。第四个参数origin_req_host指的是请求方的host名称或者IP地址。第六个参数method是一个字符串,表示请求的方法,GET,POST,PUT。
from urllib import request, parse
url = "http://httpbin.org/post"
headers = {
"User-Agent":"MOzilla/4.0(compatible;MSIE5.5;Windows NT)",
"Host":"httpbin.org"
}
dict = {
"name":"lll"
}
data = bytes(parse.urlencode(dict), encoding="utf-8")
req = request.Request(url = url, data=data, headers=headers, method="POST")
response = request.urlopen(req)
print(response.read().decode("utf-8"))
3.登陆验证
有些网站需要登陆验证,需要输入用户名和密码。
这时需要借助HTTPBasicAuthHandler可以完成,对于一些高级操作,我们需要用到urllib模块里面的BaseHandler类,它是其他Handler的父类。
from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLError
username = "username"
password = "password"
url = "http://localhost:5000/"
p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
auth_handler = HTTPBasicAuthHandler(p)
opener = build_opener(auth_handler)
try:
result = opener.open(url)
html = result.read().decode("utf-8")
print(html)
except URLError as e:
print(e.reason)
首先需要实例化HTTPBasicAuthHandler对象,参数是HTTPPasswordMgrWithDefaultRealm对象,利用add_password()添加用户名和密码。整个过程还是比较麻烦的,之后Python会有更方便的库来完成上述工作。
4.代理
做爬虫的过程中使用代理是非常常见的情况,如果需要添加代理,可以这样做。
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy_handler = ProxyHandler({
"http":"http://127.0.0.1:9743",
"https":"https://127.0.0.1:9743"
})
opener = build_opener(proxy_handler)
try:
response = opener.open("https://www.baidu.com")
print(response.read().decode("utf-8"))
except URLError as e:
print(e.reason)
5.处理异常
URLError:来自urllib库的error模块,具有reason属性,返回错误的原因。
HTTPError:URLError的子类,专门处理HTTP请求的错误,有三个属性,code(返回状态码),reason(返回错误原因),headers(返回请求头)
from urllib import request, error
try:
response = request.urlopen("https://cuiqingcai.com/index.htm")
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep="\n")
except error.URLError as e:
print(e.reason)
else:
print("successfully")
6.解析链接
urllib库还提供了parse模块,可以帮助我们处理URL的标准接口,实现URL的各部分的抽取,合并,链接转换。由于Python爬虫的库种类太多,所以我只列出了每个库较为常用的方法,之后会补充其他有用的方法。