爬虫入门之urllib库详解(二)

1 urllib模块

  1. urllib模块是一个运用于URL的包
  2. urllib.request用于访问和读取URLS
  3. urllib.error包括了所有urllib.request导致的异常
  4. urllib.parse用于解析URLS
  5. urllib.robotparser用于解析robots.txt文件(网络蜘蛛)

2 urllib读取网页的三种方式

urlopen直接打开

  1. urlopen返回对象提供的方法
  2. read() , readline() ,readlines() , fileno() , close() :对HTTPResponse类型数据进行操作
  3. info(): 返回HTTPMessage对象,表示远程服务器返回的头信息
  4. getcode():返回Http状态码。如果是http请求,200请求成功完成;404网址未找到
  5. geturl(): 返回请求的url
  6. url = "http://www.baidu.com"
  7. response = urllib.request.urlopen(url)
  8. print(response)
  9. import urllib.request
  10. response = urllib.request.urlopen('http://python.org/')
  11. html = response.read()

采用User-Agent (用户代理,简称UA)

  1. UA用来包装头部的数据:
  2. -User-Agent :这个头部可以携带如下几条信息:浏览器名和版本号、操作系统名和版本号、默认语言
  3. -Referer:可以用来防止盗链,有一些网站图片显示来源http://***.com,就是检查Referer来鉴定的
  4. -Connection:表示连接状态,记录Session的状态
  5. header = {
  6. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"}
  7. request = urllib.request.Request(url, headers=header) # 构造一个请求对象发送请求,伪装浏览器访问
  8. response = urllib.request.urlopen(req)
  1. #常用的消息包头
  2. - Accept:text/html,image/* (告诉服务器,浏览器可以接受文本,网页图片)
  3. - Accept-Charaset:ISO-8859-1 [接受字符编码:iso-8859-1]
  4. - Accept-Encoding:gzip,compress [可以接受 gzip,compress压缩后数据]
  5. - Accept-Language:zh-cn [浏览器支持的语言]
  6. - Host:localhost:8080 [浏览器要找的主机]
  7. - Referer:http://localhost:8080/test/abc.html [告诉服务器我来自哪里,常用于防止下载,盗链]
  8. - User-Agent:Mozilla/4.0(Com...) [告诉服务器我的浏览器内核]
  9. - Cookie: [会话]
  10. - Connection:close/Keep-Alive [保持链接,发完数据后,我不关闭链接]
  11. - Date: [浏览器发送数据的请求时间]

定制header信息

在 HTTP Request 中加入特定的 Header,来构造一个完整的HTTP请求消息。

可以通过调用Request.add_header() 添加/修改一个特定的header 也可以通过调用Request.get_header()来查看已有的header。

  1. request.add_header("Connection", "keep-alive") # 一直活着
  2. print(request.get_full_url()) # 访问的网页链接
  3. print(request.get_host()) # 服务器域名
  4. print(request.get_method()) # get或post
  5. print(request.get_type()) # http/https/ftp
  6. response = urllib.request.urlopen(request)
  7. print(response.code) # 状态码200, 404,500
  8. print(response.info) # 网页详细信息
  9. data = response.read().decode("gb2312")
  10. print(response.code) # 响应状态码
  11. return data

我们都知道Http协议中参数的传输是"key=value"这种简直对形式的,如果要传多个参数就需要用“&”符号对键值对进行分割。如"?name1=value1&name2=value2",这样在服务端在收到这种字符串的时候,会用“&”分割出每一个参数,然后再用“=”来分割出参数值。

3 urllib访问之get与post

1 get方式: 通过将url + ”?” + data 拼接起来赋值给新的url

四步走:

1字典数据编码key=value构建url,headers 2构建请求(url , headers) 3打开请求返回响应 4读取响应

  1. #模拟百度搜索
  2. import urllib
  3. from urllib import request
  4. import urllib.parse
  5. def baiduApi(kw):
  6. header = {
  7. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
  8. }
  9. # https://www.baidu.com/s?wd=%E5%8D%83%E9%94%8B # url编码
  10. url = 'http://www.baidu.com/s?ie=utf-8&wd='+kw #将信息拼接到url后进行构造
  11. req = urllib.request.Request(url, headers=header)
  12. response = urllib.request.urlopen(req)
  13. print(response.getcode())
  14. return response.read().decode('utf-8')
  15. if __name__ == '__main__':
  16. kw = input('请输入想查找的内容:')
  17. #百度搜索会进行url编码
  18. kw = {'kw':kw}
  19. wd = urllib.parse.urlencode(kw) #因此将字典形式的kw进行编码 wd=%E5%8D%83%E9%94%8B
  20. response = baiduApi(wd)
  21. print(response)
  22. #模拟智联招聘
  23. import urllib
  24. from urllib import request
  25. import urllib.parse
  26. import re
  27. def getJobInfo(kw):
  28. header = {
  29. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
  30. }
  31. url = "https://sou.zhaopin.com/jobs/searchresult.ashx?" + kw #get拼接
  32. req = urllib.request.Request(url,headers=header)
  33. response = urllib.request.urlopen(req) #对象
  34. html = response.read().decode('utf-8')
  35. jobNumre = '<em>(\d+)</em>' # 匹配岗位数量
  36. jobNum = re.findall(jobNumre,html) #找到符合要求的岗位数量列表
  37. return jobNum[0]
  38. if __name__ == '__main__':
  39. jobList = ['java','python','go','php']
  40. jobNumDict = {}
  41. for job in jobList:
  42. kw = {'jl':'杭州','kw':job}
  43. kw = urllib.parse.urlencode(kw) #编码例如 jl=%E6%9D%AD%E5%B7%9E&kw=java
  44. number = getJobInfo(kw)
  45. jobNumDict[job] = number
  46. print(jobNumDict)

2 post方式: 定义字典类型value,保存username和password,通过urlencode对字典编码转二进制返回给data,将数据和url通过Request方法来申请访问

五步走:

1构建headers,url 2字典转二进制data 3构建请求(url , headers,data) 4打开请求返回响应 5读取响应

  1. #抓取网易云热评
  2. import urllib.request
  3. import urllib.parse
  4. import json
  5. headers = {
  6. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
  7. }
  8. url = "https://music.163.com/weapi/v1/resource/comments/R_SO_4_547976490?csrf_token=" #url请求
  9. #form-data数据
  10. data = {
  11. "params": "3u5ErBfSCxBGdgjpJpTQyZVZgmPAv+aisCYZJ9pxk26DoOaS5on9xBjsE65yaS57u9XyxvCJIa78DXJathMsyiClN4LXqhonGNQrAtI2ajxsdW8FosN4kv8psGrRyCBsWrxSJQyfy5pfoeZwxLjB7jHtQkt9hglgZaAfj7ieRWq/XvX3DZtSgLcLrvH/SZOM",
  12. "encSecKey": "872312d7d8b04d2d5dab69d29c9bde5438337f0b3982887e3557468fe7b397de59e85ab349c07f32ef5902c40d57d023a454c3e1ed66205051264a723f20e61105752f16948e0369da48008acfd3617699f36192a75c3b26b0f9450b5663a69a7d003ffc4996e3551b74e22168b0c4edce08f9757dfbd83179148aed2a344826"
  13. }
  14. data = urllib.parse.urlencode(data).encode('utf-8') #将data转为二进制 b
  15. req = urllib.request.Request(url,headers=headers,data=data)
  16. response = urllib.request.urlopen(req)
  17. hotComment = json.loads(response.read().decode('utf-8'))
  18. hotCommentList = hotComment['hotComments']
  19. for comment in hotCommentList:
  20. userId = comment['user']['userId']
  21. nickname = comment['user']['nickname']
  22. content = comment['content']
  23. print((userId,nickname,content))

3 post请求并将数据存入数据库

  1. #抓取阿里巴巴的岗位招聘
  2. import urllib
  3. from urllib import request
  4. import json
  5. import urllib.parse
  6. import pymysql
  7. headers = {
  8. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
  9. }
  10. url = 'https://job.alibaba.com/zhaopin/socialPositionList/doList.json' #url请求获取
  11. for i in range(0,20):
  12. data = { #form-data获取的data数据
  13. 'pageSize': 10,
  14. 't': 0.9980968383643134,
  15. 'pageIndex': i
  16. }
  17. data = urllib.parse.urlencode(data).encode('utf-8') #url 编码 数据必须转为二进制
  18. req = urllib.request.Request(url,headers=headers,data=data) #Request必须接收二进制的data
  19. response = urllib.request.urlopen(req)
  20. jsonData = json.loads(response.read().decode('utf-8'))
  21. jobList = jsonData['returnValue']['datas']
  22. for job in jobList:
  23. degree = job['degree'] # 学历
  24. departmentName = job["departmentName"] # 部门
  25. description = job['description'] # 岗位要求
  26. firstCategory = job['firstCategory'] # 类型
  27. workExperience = job['workExperience'] # 要求
  28. with open('ali.txt','a+',encoding='utf-8',errors='ignore') as f: #将数据写入txt文本
  29. f.write(str((degree,departmentName,description,firstCategory,workExperience))+'\n')
  30. f.flush()
  31. #创建连接
  32. conn = pymysql.connect(host='ip地址', user='root', password="密码",database='spidder', port=3306,charset='utf8')
  33. #创建游标
  34. cursor = conn.cursor()
  35. with open('ali.txt','r',encoding='utf-8',errors='ignore') as f:
  36. while True:
  37. jobTextInfo = f.readline()
  38. if not jobTextInfo:
  39. break
  40. jobTextInfo = eval(jobTextInfo)
  41. #插入sql语句
  42. sql = 'insert into ali(degree,departmentName,description,firstCategory,workExperience) VALUES (%r,%r,%r,%r,%r)' %(jobTextInfo[0], jobTextInfo[1], jobTextInfo[2], jobTextInfo[3], jobTextInfo[4])
  43. cursor.execute(sql) #执行sql语句
  44. conn.commit() #提交
  45. #关闭连接
  46. cursor.close()
  47. conn.close()

4 json编码解析

当请求响应结果为json数据时,出现了二进制编码转不了情况,可以设置为非ascii编码

  1. import urllib.request
  2. import urllib.parse
  3. import json
  4. headers = {
  5. "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
  6. }
  7. post_url = "http://fanyi.baidu.com/sug"
  8. data = {
  9. "kw":"baby"
  10. }
  11. data = urllib.parse.urlencode(data).encode('utf-8')
  12. req = urllib.request.Request(url=post_url,headers=headers,data=data)
  13. response = urllib.request.urlopen(req)
  14. content = response.read().decode('utf-8') #str字符串,但是嵌套的数据没解析为中文
  15. #将字符串转json对象
  16. obj = json.loads(content)
  17. #将json对象转换成非ascii编码对象
  18. string = json.dumps(obj,ensure_ascii=False)
  19. print(string)
  20. #输出
  21. {"errno": 0, "data": [{"k": "baby", "v": "n. 婴儿; 婴孩; 幼崽; 宝贝儿; vt. 把…当作婴孩看待,娇养; 纵容; adj. 孩子的;"}, {"k": "babysitter", "v": "n. 临时照顾幼儿者;"}, {"k": "babysit", "v": "vi. 临时受雇代外出的父母照料小孩;"}, {"k": "babysitting", "v": "n. 托婴服务; v. 临时受雇代外出的父母照料小孩( babysit的现在分词 );"}, {"k": "baby sitter", "v": "n. <美>代人临时照顾婴孩者;"}]}

4 处理HTTPS请求 SSL证书验证

现在随处可见 https 开头的网站,urllib2可以为 HTTPS 请求验证SSL证书,就像web浏览器一样,如果网站的SSL证书是经过CA认证的,则能够正常访问,如:https://www.baidu.com/等...

如果SSL证书验证不通过,或者操作系统不信任服务器的安全证书,比如浏览器在访问12306网站如:https://www.12306.cn/mormhweb/的时候,会警告用户证书不受信任。(据说 12306 网站证书是自己做的,没有通过CA认证)

  1. import urllib
  2. from urllib import request
  3. # 1. 导入Python SSL处理模块
  4. import ssl
  5. # 2. 表示忽略未经核实的SSL证书认证
  6. context = ssl._create_unverified_context()
  7. url = "https://www.12306.cn/mormhweb/"
  8. headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
  9. request = urllib.request.Request(url, headers = headers)
  10. # 3. 在urlopen()方法里 指明添加 context 参数
  11. response = urllib.request.urlopen(request, context = context)
  12. print(response.read().decode())

5 封装

常见功能可以进行简单的封装

  1. import urllib.request
  2. import urllib.parse
  3. def create_request(category,page):
  4. headers = {
  5. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
  6. }
  7. base_url = "http://tieba.baidu.com/f?ie=utf-8&"
  8. data = {
  9. 'kw':category,
  10. 'pn':(page-1)*50
  11. }
  12. data = urllib.parse.urlencode(data)
  13. url = base_url + data
  14. req = urllib.request.Request(url,headers=headers)
  15. return req
  16. def get_content(request):
  17. response = urllib.request.urlopen(request)
  18. content = response.read().decode('utf-8')
  19. return content
  20. def save_path(content,path,page):
  21. filename = path + 'tieba' + str(page) + '.html'
  22. with open(filename,'w',encoding='utf-8') as fp:
  23. fp.write(content)
  24. def main():
  25. category = input('请输入查询类型:')
  26. start_page = int(input('请输入起始页码:'))
  27. end_page = int(input('请输入终止页码:'))
  28. print('数据下载中..')
  29. for page in range(start_page,end_page+1):
  30. request = create_request(category,page)
  31. content = get_content(request)
  32. save_path(content,'./tieba',page)
  33. print('下载成功')
  34. if __name__ == '__main__':
  35. main()

爬虫入门之urllib库详解(二)的更多相关文章

  1. Python爬虫系列-Urllib库详解

    Urllib库详解 Python内置的Http请求库: * urllib.request 请求模块 * urllib.error 异常处理模块 * urllib.parse url解析模块 * url ...

  2. 爬虫入门之urllib库(一)

    1 爬虫概述 (1)互联网爬虫 一个程序,根据Url进行爬取网页,获取有用信息 (2)核心任务 爬取网页 解析数据 难点 :爬虫和反爬虫之间的博弈 (3)爬虫语言 php 多进程和多线程支持不好 ja ...

  3. Python爬虫入门之Urllib库的高级用法

    1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...

  4. Python爬虫入门之Urllib库的基本使用

    那么接下来,小伙伴们就一起和我真正迈向我们的爬虫之路吧. 1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解 ...

  5. Python爬虫入门:Urllib库的基本使用

    1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它 是一段HTML代码,加 JS.CS ...

  6. 芝麻HTTP:Python爬虫入门之Urllib库的基本使用

    1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它是一段HTML代码,加 JS.CSS ...

  7. 爬虫(二):Urllib库详解

    什么是Urllib: python内置的HTTP请求库 urllib.request : 请求模块 urllib.error : 异常处理模块 urllib.parse: url解析模块 urllib ...

  8. python爬虫知识点总结(三)urllib库详解

    一.什么是Urllib? 官方学习文档:https://docs.python.org/3/library/urllib.html 廖雪峰的网站:https://www.liaoxuefeng.com ...

  9. 爬虫--Urllib库详解

    1.什么是Urllib? 2.相比Python2的变化 3.用法讲解 (1)urlopen urlllb.request.urlopen(url,data=None[timeout,],cahle=N ...

随机推荐

  1. POJ1064 Cable master 【二分找最大值】

    题目:题目太长了! https://vjudge.net/problem/POJ-1064 题意分析:给了你N根长度为小数形式的棍子,再给出了你需要分的棍子的数量K,但要求你这K根棍子的长度必须是一样 ...

  2. 洛谷 P4269 / loj 2041 [SHOI2015] 聚变反应炉 题解【贪心】【DP】

    树上游戏..二合一? 题目描述 曾经发明了零件组装机的发明家 SHTSC 又公开了他的新发明:聚变反应炉--一种可以产生大量清洁能量的神秘装置. 众所周知,利用核聚变产生的能量有两个难点:一是控制核聚 ...

  3. ZOJ - 1108 输出DP方案

    DP方程太水不解释 熟悉一下输出的套路 #include<iostream> #include<algorithm> #include<cstdio> #inclu ...

  4. POJ - 2528 奇怪的测试数据

    听说POJ内部测试数据有问题 我这份代码是WA的(UPD:第二份是AC代码),不过目前把discuss的数据试了一下没毛病 自己试了几组好像也没毛病? 感觉线段树部分的简单hash处理方法还是值得学习 ...

  5. Node.js frameworks

    1. Express 2. Koa 3. LoopBack egghead.io What is egghead? egghead is a group of working web developm ...

  6. <th>折行显示

    设置了一些框架的样式导致折行显示失效,解决办法: https://jingyan.baidu.com/article/3a2f7c2e24cd1826afd611e7.html

  7. http请求报文和响应报文(2)

    接上篇: 3.回应报文 理解回应报文,首先要弄清回应报文中的状态码. 相比于请求报文,对于响应报文,个人觉得还蛮有趣的. 主要由三部分组成:协议版本.状态码.状态码描述 3.1状态码 **常见的状态码 ...

  8. DP Intro - Tree DP

    二叉苹果树 题目 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点 ...

  9. oracle trim不掉空白字符分享(转)

    本文转自:http://www.2cto.com/database/201306/223558.html 问题背景:一个工商注册号,正常的用trim能解决的问题,但是这个case,trim后和肉眼看到 ...

  10. TOJ 2888 Pearls

    Description In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces ...