正则
from urllib import request
from urllib import error
class CollegateRank(object):
def get_page_data(self,url):
response = self.send_request(url=url)
if response:
# print(response)
with open('page.html','w',encoding='gbk') as file:
file.write(response)
self.parse_page_data(response)
#继续提取下一页,继续发起请求
def parse_page_data(self,response):
pattern = re.compile('<div\sclass="scores_List">(.*?)<ul\sclass="fany">',re.S)
sub_str = re.findall(pattern,response)[0]
#解析分页列表数据
pattern = re.compile(
'<dl>.*?<a\shref="(.*?)".*?>'+
'.*?<img.*?src="(.*?)".*?>'+
'.*?<a.*?>(.*?)</a>'+
'.*?<li>.*?:(.*?)</li>'+
'.*?<li>(.*?)</li>'+
'.*?<li>.*?:(.*?)</li>'+
'.*?<li>.*?:(.*?)</li>'+
'.*?<li>.*?:(.*?)</li>'+
'.*?<li>.*?:(.*?)</li>.*?</dl>',
re.S
)
ranks = re.findall(pattern,sub_str)
print(ranks)
for item in ranks:
school_info = {}
school_info['url'] = item[0] #详情url地址
school_info['icon'] = item[1]
school_info['name'] = item[2]
school_info['adress'] = item[3]
school_info['tese'] = '、'.join(re.findall('<span.*?>(.*?)</span>',item[4]))
school_info['type'] = item[5]
school_info['belong'] = item[6]
school_info['level'] = item[7]
school_info['weburl'] = item[8]
print(school_info)
xiangqing = self.send_request(url=school_info['url'])
pattern = re.compile(
'<dd\sclass="left">.*?<li>.*?</li>.*?<li>.*?</li>.*?<li>.*?</li>.*?<li>(.*?)</li>.*?<p>.*?:(.*?)<br />.*?:(.*?)<br />.*?:(.*?)<br />.*?</p >',
re.S)
ranks = re.findall(pattern, xiangqing)
for item in ranks:
school_info['yuanshi'] = item[0]
school_info['dizhi'] = item[1]
school_info['phone'] = item[2]
school_info['email'] = item[3]
print(school_info)
def send_request(self,url,headers=None):
headers = headers if headers else {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}
req = request.Request(
url=url,
headers = headers,
)
try:
response = request.urlopen(req,timeout=10)
if response.code == 200:
return response.read().decode('gb2312')
except error.HTTPError as err:
print(err.reason)
except error.URLError as err:
print(err.reason)
if name == ‘main’:
url = ‘http://college.gaokao.com/schlist/’
obj = CollegateRank()
obj.get_page_data(url)
"""
. 匹配除了换行符之外的任意字符
\d 匹配数字0-9 =>[0-9] => ^\D
\D 匹配非数字
\s 匹配空白字符(空格 \n \r \t)
\S 匹配非空白字符
\w 匹配单词字符[a-zA-Z0-9_]
\W 匹配非单词字符
^ 以...开头
$ 以...结尾
[0-9a-z] :表示匹配数字0~9,字母a~z
[^a-z] : 不匹配a-z之间的字符
#多字符匹配,贪婪模式
* 匹配*号前的字符任意次数
+ 匹配+号前的字符至少一次
?匹配?号前的字符0~1次
#多字符匹配,非贪婪模式 (abcdeabcde) e
*?
+?
??
| 或
() 分组
"""
import re
"""
re.match():匹配字符串的开头,有符合正则规则则子串,返回结果match对象,
没有匹配到结果,返回None,单次匹配
re.search():从字符串开头,在整个字符串中进行匹配,有符合正则规则则子串
,返回结果match对象,没有匹配到结果,返回None,单次匹配
re.findall():在整个字符串中匹配所有符合正则规则的结果,返回一个list
re.finditer():在整个字符串中匹配所有符合正则规则的结果,返回一个可叠代对象
re.sub():在整个字符串中,替换所有符合正则表达式的子串
re.split() :根据正则表达式,分割字符串,返回一个list
"""
**urlib_post**
from urllib import request
from urllib import parse
from urllib import error
import json
url = ‘http://127.0.0.1:8001/api/loginxxx/’
data = {
‘username’:‘18086457367’,
‘password’:‘abc123456’,
}
data = parse.urlencode(data).encode(‘utf-8’)
print(’=’,data)
#构建request对象(添加请求头)
headers = {
‘User-Agent’:‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36’,
}
req = request.Request(
url=url,data=data,headers=headers
)
#= username=18086457367&password=abc123456
#===== b’username=18086457367&password=abc123456’
response = request.urlopen(
url=url,data=data,timeout=10
)
try:
response = request.urlopen(
req,timeout=10
)
except error.HTTPError as err:
print(err.code)
print(err.headers)
print(err.reason)
except error.URLError as err:
print(err.reason)
print(response.code)
content = response.read().decode(‘utf-8’)
result = json.loads(content)
print(content,type(result))
#dict类型的取值方式
print(result[‘token’])
print(result.get(‘token’,‘暂无’))
json.loads():将json字符串,转换为python数据类型
json.load():将本地文件中的json字符串,转换为python数据类型
json.dumps():将python数据类型,转换为json字符串****
json.dump():将python数据类型,转换为json字符串,并写入到本地文件******
**urlib_parse**
from urllib import parse
parse.urlencode():将字典类型的参数转为url编码格
data = {
‘username’:‘xxx’,
‘password’:‘abc’
}
data = parse.urlencode(data)
print(data)
parse.parse_qs():将url编码格式的字符串转化为字典类型
data = parse.parse_qs(data)
print(data)
#中文
#parse.quote()将中文字符转为url编码的字符
#wd=%E7%BE%8E%E5%A5%B3
wd=“美女”
wd = parse.quote(wd)
print(wd) #%E7%BE%8E%E5%A5%B3
#parse.unquote()将url编码的字符转换为中文字符
wd = parse.unquote(wd)
print(wd) #美女
#parse.urljoin将不完整的url参照基类url,拼接完整
base_url = ‘http://www.baidu.com/?wd=xxx’
sub_url = ‘?page=1&pagesize=10’
full_url = parse.urljoin(base_url,sub_url)
print(full_url) #http://www.baidu.com/?page=1&pagesize=10
parse.urlencode():将字典类型的参数转为url编码格
parse.parse_qs():将url编码格式的字符串转化为字典类型
中文
parse.quote()将中文字符转为url编码的字符
wd=%E7%BE%8E%E5%A5%B3
parse.unquote()将url编码的字符转换为中文字符
parse.urljoin将不完整的url参照基类url,拼接完整
**urlib_proxy**
#自定义opener方法,设置代理发起请求
from urllib import request
import ssl
#创建HTTPSHandler处理器,支持发起https请求,忽略ssl认证
context = ssl._create_unverified_context()
https_handler = request.HTTPSHandler(
debuglevel=1,
context=context,
)
#创建ProxyHandler代理处理器,允许发起请求时设置代理
proxies = {
‘http’:‘192.168.1.111:8080’,
‘https’:‘192.168.1.122:8080’,
}
proxy_handler = request.ProxyHandler(proxies=proxies)
#根据处理器,自定义opener
opener = request.build_opener(https_handler,proxies)
##将opener设置为全局的opener,这时候使用urlopner方法发起请求就会只用
#自定义的opener
request.install_opener(opener)
headers = {
‘User-Agent’:‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36’,
}
req = request.Request(
url=‘https://www.baidu.com’,
headers=headers
)
#发起请求
response = opener.open(req,timeout=10)
response = request.urlopen(req,timeout=10)
print(response.code)
urllib:
是python自带抓取网页的其中的一种
urllib的三个属性:
request: 它是最基本的HTTP请求模块,可以用来模拟发送请求,就像在浏览器中输入网址,然后敲击回车键一样
error: 异常处理模块,如果出现请求错误,我们可以使用这个模块来捕获异常,然后进行重试或者其他操作,保证程序不会意外终止.
parse: 这一个工具模块,提供了许多url的处理方法,比如拆分,解析,合并
urllib里的urlopen的常见参数用法:
* url:设置目标url
* data:如果设置该参数,则请求默认为post请求
* timeout:用于设置超时时间,单位为秒
* context:必须是一个ssl.SSLContext类型,用来指定SSL设置,忽略未认证的CA证书
urilib的Request:
使用urlopen直接发送请求,获取一些反爬手段低的网站,有些网站会根据请求头来判断是否是浏览器访问,则需要增加HTTP报头,必须创建一个 Request 实例来作为urlopen()的参数;而需要访问的url地址则作为 Request 实例的参数。
* url 参数是请求链接,这个是必传参数,其他的都是可选参数。
* data(默认空) 参数跟 urlopen() 中的 data 参数用法相同。
* headers(默认空) 是一个字典。它除了在 Request 中添加,还可以通过调用 Reques t实例的 add_header() 方法来添加请求头。
* unverifiable 参数表示这个请求是否是无法验证的,默认值是False。意思就是说用户没有足够权限来选择接收这个请求的结果。例如我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,我们就要将 unverifiable 的值设置成 True。(这个参数我们不需要设置)
* method 参数指的是发起的 HTTP 请求的方式
urllib 的异常错误及错误处理
URLError:来自urllib库的error模块,继承自OSError,由request模块产生的异常都可以通过捕捉这个类来处理.
产生的原因主要有:
* 没有网络连接
* 服务器连接失败
* 找不到指定的服务器
它具有一个属性reason,返回错误的原因
HTTPError
* HTTPError是URLError的子类,我们发出一个请求时,服务器上都会对应一个response应答对象,其中它包含一个数字"响应状态码"。
* 专门用来处理HTTP请求错误,比如未认证,页面不存在等
* 有三个属性:
* code:返回HTTP的状态码
* reason:返回错误原因
* headers:返回请求头
具体使用,因为HTTPError的父类是URLError,所以我们更好的处理顺序应该是先捕获子类的错误,再捕获父类的错误
parse模块下常用的url解析、合并、编码、解码方法
用时先导入
from urllib import parse
parse里面的几种用法:
urlencode()将字典构形式的参数序列化为url编码后的字符串
parse_qs()将url编码格式的参数反序列化为字典类型
quote()可以将中文转换为URL编码格式
unquote:可以将URL编码进行解码
urljoin()传递一个基础链接,根据基础链接可以将某一个不完整的链接拼接为一个完整链接
urlparse()实现URL的识别和分段
urlunparse()可以实现URL的构造
正则的用法:
匹配单个字符
. 匹配除了换行符之外的任意字符
\d 匹配数字0-9 =>[0-9] => ^\D
\D 匹配非数字
\s 匹配空白字符(空格 \n \r \t)
\S 匹配非空白字符
\w 匹配单词字符[a-zA-Z0-9_]
\W 匹配非单词字符
^ 以...开头
$ 以...结尾
[0-9a-z] :表示匹配数字0~9,字母a~z
[^a-z] : 不匹配a-z之间的字符
多字符匹配,贪婪模式
* 匹配*号前的字符任意次数
+ 匹配+号前的字符至少一次
?匹配?号前的字符0~1次
多字符匹配,非贪婪模式 (abcdeabcde) e
*?
+?
??
| 或
() 分组
正则的五种用法:
re.match():匹配字符串的开头,有符合正则规则则子串,返回结果match对象,
没有匹配到结果,返回None,单次匹配
re.search():从字符串开头,在整个字符串中进行匹配,有符合正则规则则子串
,返回结果match对象,没有匹配到结果,返回None,单次匹配
re.findall():在整个字符串中匹配所有符合正则规则的结果,返回一个list
re.finditer():在整个字符串中匹配所有符合正则规则的结果,返回一个可叠代对象
re.sub():在整个字符串中,替换所有符合正则表达式的子串
re.split() :根据正则表达式,分割字符串,返回一个list