urllib属于python3.x自带的库,功能比较简单,可以拿来入门和练手。
官方手册:https://docs.python.org/3/library/urllib.html
+ 简单操作
import urllib.request
data = urllib.request.urlopen('https://www.douban.com')
print(data.version,data.status,data.reason,data.closed)
print(data.read().decode('utf-8'))
通过HTTP Analyzer抓包显示urlopen发送的网页请求内容为:
GET / HTTP/1.1
Accept-Encoding: identity
Host: www.douban.com
User-Agent: Python-urllib/3.6
Connection: close
+ 模拟浏览器访问
模拟浏览器需要使用urllib.request.Request对象
import urllib.request
url = "https://www.douban.com"
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.64',
'Host':'www.douban.com',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Connection':'keep-alive'}
request = urllib.request.Request(url=url,headers=headers)
data = urllib.request.urlopen(request)
print(data.status)
+ post数据到服务器
如果要以POST发送一个请求,只需要把参数data以bytes形式传入。
import urllib.request
import urllib.parse
url = "http://httpbin.org/post"
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.64',
'Host':'httpbin.org',}
dict = {'name':'chenkaifang'}
data = urllib.parse.urlencode(dict).encode('utf-8')
request = urllib.request.Request(url=url,headers=headers,method='POST')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))
+ 简单模拟登陆
提交用户登录信息(用户名和密码),不同网站可能需要的东西不一样。parse的 urlencode 方法是将一个字典或者有顺序的二元素元组转换成为URL的查询字符串。
使用Cookie和使用代理IP一样,也需要创建一个自己的opener。在HTTP包中,提供了cookiejar模块,用于提供对Cookie的支持。http.cookiejar功能强大,我们可以利用本模块的CookieJar类的对象来捕获cookie并在后续连接请求时重新发送,比如可以实现模拟登录功能。该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。
它们的关系: CookieJar–派生–>FileCookieJar–派生–>MozillaCookieJar和LWPCookieJar
工作原理:创建一个带有cookie的opener,在访问登录的URL时,将登录后的cookie保存下来,然后利用这个cookie来访问其他网址。查看登录之后才能看到的信息。
(1)首次无cookie手动输入验证码登陆豆瓣
首次无cookie登陆有时需要用户输入验证码,可以将验证码图片下载到本地后手动输入,请求头和POST数据可以在浏览器中登陆检查元素(勾选Preserve log)找到浏览器发出的Login请求包,根据其格式填写自己的请求头。
import urllib.parse
import urllib.request
import re
import time
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.68',
'Host':'accounts.douban.com',
'Connection':'keep-alive',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Referer':'https://accounts.douban.com/login',
'Accept-Encoding':'zip, deflate, br',
'Accept-Language':'zh-CN,zh;q=0.9'
}
values = {'source':'None',
'redir':'https://www.douban.com',
'form_email':'xxx',
'form_password':'yyy',
'login':'登陆',
}
url = "https://accounts.douban.com/login"
request = urllib.request.Request(url=url, headers=headers)
def get_captcha_info():
captcha_info = dict()
response = urllib.request.urlopen(request)
if response.status == 200:
html = response.read().decode('UTF-8')
link_list = re.findall(r'src="https://www.douban.com.*?captcha.*?"', str(html))
link = link_list[0][5:-1]
urllib.request.urlretrieve(link,'xx.jpg')
print(link)
captcha_solution = input('请输入验证码:')
captcha_info['captcha-solution'] = captcha_solution
captcha_id_list = re.findall(r'id=.*?&',link)
captcha_id = captcha_id_list[0][3:-1]
captcha_info['captcha-id'] = captcha_id
return captcha_info
captcha_info = get_captcha_info()
if captcha_info:
values.update(captcha_info)
time.sleep(3)
data = urllib.parse.urlencode(values).encode('UTF-8')
request = urllib.request.Request(url=url,data = data,headers=headers)
response = urllib.request.urlopen(request)
print(response.status,response.version,response.reason,response.geturl())
print(response.read().decode('UTF-8'))
(2)首次携带cookie手动输入验证码登陆豆瓣
import urllib.parse
import urllib.request
import re
import time
import http.cookiejar
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.68',
'Host':'accounts.douban.com',
'Connection':'keep-alive',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Referer':'https://accounts.douban.com/login',
'Accept-Encoding':'zip, deflate, br',
'Accept-Language':'zh-CN,zh;q=0.9'
}
values = {'source':'None',
'redir':'https://www.douban.com',
'form_email':'xxx',
'form_password':'yyy',
'login':'登陆',
}
url = "https://accounts.douban.com/login"
request = urllib.request.Request(url=url, headers=headers)
cookie = http.cookiejar.CookieJar()
cookie_support = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(cookie_support)
def get_captcha_info():
captcha_info = dict()
response = opener.open(request)
if response.status == 200:
html = response.read().decode('UTF-8')
link_list = re.findall(r'src="https://www.douban.com.*?captcha.*?"', str(html))
link = link_list[0][5:-1]
urllib.request.urlretrieve(link,'xx.jpg')
print(link)
captcha_solution = input('请输入验证码:')
captcha_info['captcha-solution'] = captcha_solution
captcha_id_list = re.findall(r'id=.*?&',link)
captcha_id = captcha_id_list[0][3:-1]
captcha_info['captcha-id'] = captcha_id
return captcha_info
captcha_info = get_captcha_info()
if captcha_info:
values.update(captcha_info)
time.sleep(3)
data = urllib.parse.urlencode(values).encode('UTF-8')
request = urllib.request.Request(url=url,data = data,headers=headers)
response = opener.open(request)
print(response.status,response.version,response.reason,response.geturl())
print(response.read().decode('UTF-8'))
+ 爬取网页上的图片实例 urllib.request + re
import urllib.request
import socket
import re
import sys
import os
targetDir = r"D:\project\webdownload"
def destFile(path):
if not os.path.isdir(targetDir):
os.mkdir(targetDir)
pos = path.rindex('/')
t = os.path.join(targetDir,path[pos+1:])
return t
#url="https://www.douban.com/"
url="http://www.netbian.com/"
webheader={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}
req = urllib.request.Request(url=url,headers=webheader)
webPage = urllib.request.urlopen(req)
#data = webPage.read().decode('UTF-8')
data = webPage.read().decode('gbk')
'''print(data)'''
'''对于re.findall,如果有多个匹配group,则会返回类似(xxx,yyy)的tuple,所以下面用link,t'''
for link,t in set(re.findall(r'(http:[^\s]*?(jpg|png|gif))', str(data))):
print(link)
try:
urllib.request.urlretrieve(link, destFile(link))
except():
print('失败')
(1)利用urllib.request.urlretrieve(url, filename = 本地文件地址)。
(2)一般来说,URL标准中只会允许一部分ASCII字符比如数字、字母、部分符号等,而其他的一些字符,比如汉字等,是不符合URL标准的。此时,我们需要编码。如果要进行编码,我们可以使用urllib.request.quote()进行。
(3)用F12显示网页采用的charset=gb2312的编码,但是用decode("gb2312")时报错:UnicodeDecodeError: 'gb2312' codec can't decode byte 0x90 in position 34461: illegal multibyte sequence。
解决方案:使用第三方库chardet检测网页的真正编码方式,如果安装了Anaconda,chardet就已经可用了。chardet.detect(xxx)可以用来检测编码方式。
(4)gb2312编码的网页不需要解码直接使用正则即可。
(5)遇到/uploads/.../.jpg路径,实际图片下载路径为当前网址加上此路径。
(6)网页分为动态、静态和伪静态,htm或html静态或伪静态,asp、jsp、php、shtml等动态文件。javascript:alert(document.lastModified),将这句代码粘贴到所要测试页面的地址栏,回车即可出现时间提示。经过测试,静态页面提示的时间与系统时间不一样,而伪静态或动态页面则提示的时间与系统时间相同。urlopen的response中getheaders的Last-Modified返回最新修改时间。
(7)urllib.request适用于静态网页。