环境
- Win7+Python2.7
- urllib+urllib2
[!] urllib模块和urllib2模块的区别
urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL。
urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。
工作流程
定位需要爬取的页面,糗事百科首页https://www.qiushibaike.com/
用urllib2的Request类构建一个request
url = "https://www.qiushibaike.com/"
request = urllib2.Request(url)
接下来用urllib2的urlopen方法来请求页面,并获取响应(即页面内容)
response = urllib2.urlopen(request)
打印获取到的内容
print response.read()
运行我们的脚本,结果报错了:
Traceback (most recent call last):
File "00_get_a_page.py", line 19, in <module>
response = urllib2.urlopen(request)
File "D:\Python27\lib\urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "D:\Python27\lib\urllib2.py", line 429, in open
response = self._open(req, data)
File "D:\Python27\lib\urllib2.py", line 447, in _open
'_open', req)
File "D:\Python27\lib\urllib2.py", line 407, in _call_chain
result = func(*args)
File "D:\Python27\lib\urllib2.py", line 1241, in https_open
context=self._context)
File "D:\Python27\lib\urllib2.py", line 1201, in do_open
r = h.getresponse(buffering=True)
File "D:\Python27\lib\httplib.py", line 1121, in getresponse
response.begin()
File "D:\Python27\lib\httplib.py", line 438, in begin
version, status, reason = self._read_status()
File "D:\Python27\lib\httplib.py", line 402, in _read_status
raise BadStatusLine(line)
httplib.BadStatusLine: ''
这是因为糗事百科针对爬虫的一些反爬优化,必须是浏览器才能访问页面。
不过没关系,浏览器的信息是通过headers
实现的,我们可以用urllib2设置浏览器信息头,把我们的程序伪装成浏览器。
设置头部验证信息
user_agent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36 LBBROWSER"
headers = {"User-Agent":user_agent}
可以看到我们设置了User-Agent
这个字段,并将其封装为一个字典headers
,后面我们会用到这个headers
。
user_agent
的内容是Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36 LBBROWSER
,这个是我是用的猎豹浏览器的头部信息,通过F12开发者工具可以查看到。
重新构造请求,并打印获取到的响应页面的内容
request = urllib2.Request(url,headers=headers)
可以发现我们在构造request时除了url参数,还将刚才封装好的带有浏览器信息的headers
传给了urllib2.Request
的headers参数。
[!] 必须指定headers=headers
,否则会默认将headers传递给urllib2.Request的第二个参数,但是第二个参数并非headers,如下:
>>> help("urllib2.Request")
Help on class Request in urllib2:
urllib2.Request = class Request
| Methods defined here:
| __getattr__(self, attr)
| __init__(self, url, data=None, headers={}, origin_req_host=None, unverifiable=False)
同样的再重新请求页面,获取响应并打印出来
response = urllib2.urlopen(request)
print response.read()
获取成功!但是我们的汉字并没有显示出来。
这是因为我们获取到的response.read()的编码方式是UTF-8的字节流数据,而我们python2.7的默认编解码方式为ASCII,从而导致了乱码。
我们打印时指定解码方式为UTF-8试试看。
print response.read().decode('utf-8')
成功!
至此我们获取了完整的整个页面信息。