说明:
urllib2是python2.7自带的模块
urllib2在python3.x中被修改为urllib.request
1、urllib.request.urlopen()详解
(1)介绍 urllib.request.urlopen()函数用于实现对目标url的访问。
函数原型如下:urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
参数说明: url: 需要打开的网址,可以是一个链接,也可是一个urllib.request对象
data:发往服务器请求中的额外的参数信息(如:在线翻译,在线答题等提交的内容),data默认是None,此时以GET方式发送请求;当用户给出data参数的时候,改为POST方式发送请求
timeout:设置网站的访问超时时间
cafile、capath、cadefault 参数:用于实现可信任的CA证书的HTTP请求。(基本上很少用)
context参数:实现SSL加密传输。(基本上很少用)
(2)返回处理方法详解 urlopen返回对象提供方法:
- read() , readline() ,readlines() , fileno() , close() :对HTTPResponse类型数据进行操作
- info():返回HTTPMessage对象,表示远程服务器返回的头信息
- getcode():返回Http状态码。如果是http请求,200请求成功完成;404网址未找到
- geturl():返回请求的url(实际数据的实际url)
(3)直接用urllib.request模块的urlopen()获取页面,page的数据格式为bytes类型,需要decode()解码,转换成str类型。
(4)版本区别,注意事项
python2和python3在导入urlrequest的方式都不一样。
python2是这样:import urllib2
而python3里面把urllib分开了,分成了urlrequest和urlerror,在这里我们只需导入urlrequest即可。from urllib.request import urlopen
2、urllib简单的使用 【与requests库的对比】
get请求和post请求的区别:
- get:请求的url会附带查询参数 对于get请求:查询参数在QueryString里保存
- post:请求的url不带参数 对于post请求:查询参数在Form表单里保存
(2-1)get请求比较 此处让其带上参数paramers 【爬取贴吧信息】
""" 用于爬取贴吧上关于“***”的“起始页”-“结束页”页的内容,若***为“南京信息工程大学” 首页:http://tieba.baidu.com/f?kw=南京信息工程大学&pn=0 第一页:http://tieba.baidu.com/f?kw=南京信息工程大学&pn=50 第二页:http://tieba.baidu.com/f?kw=南京信息工程大学&pn=100 参数:kw为关键词 pn与页数相关 """ #使用urllib库爬取 from urllib.request import Request from urllib.parse import urlencode from urllib.request import urlopen def get_page_urllib(url, kw, beginPage, endPage): headers={'user-agent':'Mozilla/5.0'} for page in range(beginPage,endPage+1): pn=str((page-1)*50) params={'kw':kw,'pn':pn} params_new=urlencode(params) #此时不需要使用urlencode方法转换标准格式 url_new=url+params_new try: request = Request(url_new,headers=headers) #构造一个Request请求 r= urlopen(request) # 最后再使用urlopen()发送请求对象 print('正在爬取:{}贴吧_第{}页,网址:{}'.format(kw, page, r.url)) #r.getcode() #200,表示访问成功 html = r.read().decode('utf-8') except Exception as e: print(e) def main_urllib(): url = 'http://tieba.baidu.com/f?' kw = input('请输入需要爬取的贴吧名:').strip() beginPage = int(input('请输入起始页:').strip()) endPage = int(input('请输入结束页:').strip()) get_page_urllib(url, kw, beginPage, endPage) main_urllib() """ 请输入需要爬取的贴吧名:南京信息工程大学 请输入起始页:1 请输入结束页:3 正在爬取:南京信息工程大学贴吧_第1页,网址:http://tieba.baidu.com/f?kw=南京信息工程大学&pn=0 正在爬取:南京信息工程大学贴吧_第2页,网址:http://tieba.baidu.com/f?kw=南京信息工程大学&pn=50 正在爬取:南京信息工程大学贴吧_第3页,网址:http://tieba.baidu.com/f?kw=南京信息工程大学&pn=100 """
(2-2)post请求 【但是这个post请求不太好】post请求必须传data参数 【有道词典的翻译】
#有道翻译====>采用js加密的方式。需要破解 #formdata的解析,需要解析:salt和sign 【重点】 import time,json url='http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule' #有道翻译网址 key_word=input('请输入需要翻译的文字:').strip() #输入翻译的关键字 salt=str(int(time.time()*10000)) def get_md5(v): #得到加密字符串 import hashlib md5 = hashlib.md5() # md5对象,md5不能反解,但是加密是固定的,就是关系是一一对应,所以有缺陷,可以被对撞出来 md5.update(v.encode('utf-8')) # 要对哪个字符串进行加密,就放这里 value = md5.hexdigest() # 拿到加密字符串 return value def get_sign(key, salt): sign = 'fanyideskweb' + key + str(salt) + 'ebSeFb%=XZ%T[KZ)c(sy!' sign = get_md5(sign) return sign formdata={ "i":key_word, "from":"AUTO", "to":"AUTO", "smartresult": "dict", "client":"fanyideskweb", "salt":salt, #"1526736521130", 盐:很长的随机串,防止用字典反推 "sign":get_sign(key_word,salt), # 签名:js加密 【难点】 "ts":salt[:-1], "bv":"4aa86d26f5a1487d9d25dd7a4b9335ed", #我的电脑默认bv是该值不变 "doctype":"json", "version":"2.1", "keyfrom":"fanyi.web", "action":"FY_BY_REALTlME" } headers = { 'Cookie':"OUTFOX_SEARCH_USER_ID=710408941@222.190.109.119; _ntes_nnid=e1bc78f1e3aae9820e3a1ecdac853ab4,1526112242491; OUTFOX_SEARCH_USER_ID_NCOO=1967106265.268107; UM_distinctid=169953eeb3e536-0c1ad4d22565a1-30584d74-1fa400-169953eeb3fa8b; NTES_SESS=EkmaBViQniknHZyR8OVY7s1tdxu4s1usf.u.ANg_5XZThziQhoRng7dsDCB1Tscnr.SPvt_oisUUnIsaKekyMKqQptYbnA_25rW50eLUS7bUz8U4xcfcY2oU4tZ7_u4q26Fbgwe5qfzdd3rdzjyiNvi9a_vTqgQSbQElG4ZNtESGT8GoEnG1rlntz6vcFngasYer960lYaBU7; ANTICSRF=49c340db3252f748eaa1b657df955d47; S_INFO=1557315298|0|3&80##|pansy_nuist; P_INFO=pansy_nuist@163.com|1557315298|0|other|00&99|jis&1557303230&carddav#jis&320100#10#0#0|&0|urs&mail163|pansy_nuist@163.com; JSESSIONID=aaaxJ1OcgDRc9aSxYfHQw; ___rl__test__cookies=1557546635049", "Referer":"http://fanyi.youdao.com/", "User-Agent":"Mozilla/5.0", } #有道的请求头必须要有“Cookie”、“Referer”、“User-Agent” #使用urllib爬取有道翻译 from urllib.request import Request from urllib.parse import urlencode from urllib.request import urlopen def post_page_urllib(url): data_new = urlencode(formdata).encode() # 此时必须使用urlencode方法转换格式,因为POST请求的需要 try: # 通过urllib.request.Request()方法构造一个请求对象,有data数据,认为是post请求 request = Request(url, headers=headers, data=data_new, method='POST') r=urlopen(request) #print(r.getcode()) #200,表示访问成功 return r.read().decode('utf-8') except Exception as e: print(e) def main_urllib(): html=post_page_urllib(url) #字符串格式 data=json.loads(html) #字典格式 result=data['translateResult'][0][0]['tgt'] print('翻译结果为:{}'.format(result)) main_urllib() """ 请输入需要翻译的文字:操作系统 翻译结果为:The operating system """
3、ajax加载方式的数据获取
ajax方式加载的页面,数据来源一定是json,拿到json,就是拿到了网页的数据
"""爬取豆瓣电影分类排行榜 - 剧情片 好于100%-90%的剧情片 每次下拉,电影信息会加载出现~ #https://movie.douban.com/j/chart/top_list?type=11&interval_id=100:90&action=None&start=0&limit=20 #https://movie.douban.com/j/chart/top_list?type=11&interval_id=100:90&action=None&start=20&limit=20 #https://movie.douban.com/j/chart/top_list?type=11&interval_id=100:90&action=None&start=40&limit=20 解析发现是:get请求 其中的start参数是每次变化的 这次就只显示电影的名称 """ #使用urllib库爬取 from urllib.request import Request from urllib.parse import urlencode from urllib.request import urlopen import json def get_page_urllib(url,start): headers={'user-agent':'Mozilla/5.0'} params={'type':'11','interval_id':'100:90','action':'','start':start,'limit':'20'} params_new=urlencode(params) #此时不需要使用urlencode方法转换标准格式 url_new=url+params_new try: request = Request(url_new,headers=headers) #构造一个Request请求 r= urlopen(request) # 最后再使用urlopen()发送请求对象 #print(r.getcode()) #200,表示访问成功 html = r.read().decode('utf-8') return html except Exception as e: print(e) def movie_urllib(url,nums): for item in range(nums): #自己设置5页 start=str((item)*20) html=get_page_urllib(url,start) data=json.loads(html) for item in data: rank=item['rank'] name=item['title'] print('{}_{}'.format(rank,name)) def main_urllib(): url = 'https://movie.douban.com/j/chart/top_list?' movie_urllib(url,5) #设置爬取5页 main_urllib() #注:结果这边就不显示了,就是rank_name形式
4、利用cookie模拟登陆
【此处是最简单的方法:直接在headers出增加cookie】==>不具备普遍性!
""" 登入 人人网 http://www.renren.com/PLogin.do PS:最简单的方法:直接将cookie值作为headers中的参数 【“手动拷贝cookie”,找cookie比较麻烦,不具备广泛使用,且只能访问该cookie用户】 """ # 使用urllib登入人人网 【成功,直接将cookie值作为headers中的参数】 from urllib.request import Request from urllib.request import urlopen url='http://www.renren.com/568606842/profile' headers={ 'User-Agent':'Mozilla/5.0', 'Cookie':'anonymid=jvjhi6fzofp2b5; depovince=JS; _r01_=1; JSESSIONID=abcUT0aP7uTGL6v4h3MQw; ick_login=dc7ac056-69c6-4fde-9caf-fd8c08da8e41; _de=56C47B38358E44CDAA9A4DB303A192B0; first_login_flag=1; ln_uact=18252085787; ln_hurl=http://hdn.xnimg.cn/photos/hdn521/20141115/1635/h_main_khbw_e15300049784195a.jpg; id=568606842; ver=7.0; wp_fold=0; jebe_key=f38382a8-430b-4bd4-9be2-279c9e1313fb%7C02c0b98ec2be9c26b6d036920d78daab%7C1557580565414%7C1%7C1557580332338; jebecookies=3a897b13-0567-4a4b-8615-ff6e16b370ea|||||; p=1d011bc26ff547c254cab328a14b761f2; t=5c4f1064b378ee36f2f65c7f4722c6c12; societyguester=5c4f1064b378ee36f2f65c7f4722c6c12; xnsid=5592bd87; loginfrom=syshome', 'Referer':'http://www.renren.com/568606842/profile' } request=Request(url,headers=headers) r=urlopen(request) print(r.getcode()) #200 html=r.read().decode('utf-8') print(html) #使用requests登入人人网 【成功,使用session会话】 import requests user_name=int(input('请输入用户名:').strip()) user_pass=int(input('请输入密码:').strip()) session=requests.session() data={"email":user_name,"password":user_pass} headers={'user-agent':'Mozilla/5.0'} urlLogin = "http://www.renren.com/PLogin.do" session.post(urlLogin,data=data,headers=headers) r=session.get('http://www.renren.com/568606842/profile',headers=headers) html=r.text print(html)