[爬虫]-Urllib

发布时间:2026/7/24 10:55:56
[爬虫]-Urllib 前置知识什么是互联网爬虫?如果我们把互联网比作一张大的蜘蛛网那一台计算机上的数据便是蜘蛛网上的一个猎物而爬虫程序就是一只小蜘蛛沿着蜘蛛网抓取自己想要的数据解释1: 通过一个程序根据url(http://www.taobao.com)进行爬取网页获取有用信息 解释2:使用程序模拟浏览器去向服务器发送请求获取响应信息爬虫核心?爬取网页: 爬取整个网页 包含了网页中所有得内容。解析数据:将网页中你得到的数据进行解析难点:爬虫和反爬虫之间的博弈爬虫的用途?数据分析/人工数据集社交软件冷启动舆情监控竞争对手监控。爬虫分类?通用爬虫实例 百度、360、google、sougou等搜索引擎---伯乐在线 功能 访问网页-抓取数据-数据存储-数据处理-提供检索服务 robots协议 一个约定俗成的协议添加robots.txt文件来说明本网站哪些内容不可以被抓取起不到限制作用自己写的爬虫无需遵守。 网站排名(SEO) 1.根据pagerank算法值进行排名(参考个网站流量、点击率等指标) 2.百度竞价排名 缺点 1.抓取的数据大多是无用的 2.不能根据用户的需求来精准获取数据聚焦爬虫功能 根据需求实现爬虫程序抓取需要的数据 设计思路 1.确定要爬取的url 如何获取url 2.模拟浏览器通过http协议访问url获取服务器返回的html代码 如何访问 3.解析html字符串(根据一定规则提取需要的数据) 如何解析反爬手段?1.User-Agent User Agent中文名为用户代理简称UA它是一个特殊字符串头使得服务器能够识别客户使用的操作系统及版本、CPU类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。 2.代理IP 西次代理 快代理 什么是高匿名、匿名和透明代理?它们有什么区别? 1.使用透明代理对方服务器可以知道你使用了代理并且也知道你的真实IP。 2.使用匿名代理对方服务器可以知道你使用了代理但不知道你的真实IP。 3.使用高匿名代理对方服务器不知道你使用了代理更不知道你的真实IP。 3.验证码访问 打码平台 云打码平台 超级 4.动态加载网页 网站返回的是js数据并不是网页的真实数据 selenium驱动真实的浏览器发送请求 5.数据加密 分析js代码urllib库使用urllib使python自带的库, 主要学习以下6个方法urllib.request.urlopen() 模拟浏览器向服务器发送请求 response 服务器返回的数据 response的数据类型是HttpResponse 字节--字符串 解码decode 字符串--字节 编码encode read() 字节形式读取二进制 扩展:rede(5)返回前几个字节 readline() 读取一行 readlines() 一行一行读取 直至结束 getcode() 获取状态码 geturl() 获取url getheaders() 获取headers urllib.request.urlretrieve() 请求网页 请求图片 请求视频urllib的基本使用import urllib.request url http://www.baidu.com # 模拟浏览器向服务器发送请求 response urllib.request.urlopen(url) # 解析响应的数据 content response.read().decode(utf-8) # 打印数据 print(content)import urllib.request url http://www.baidu.com # 模拟浏览器向服务器发送请求 response urllib.request.urlopen(url) # 一个类型和6个方法 # 类型: response是一个HTTPResponse对象 print(type(response)) # 方法1: 一个字节一个字节的读取 # content response.read() # 方法2: 指定读取多少个字节 # content response.read(20) # 方法3: 读取一行 # content response.readline() # 方法4: 读取所有行 content response.readlines() # 方法5: 获取响应状态码 code response.getcode() # 方法6: 获取响应头信息 headers response.getheaders()下载import urllib.request # 下载网页 # url_page http://www.baidu.com # urllib.request.urlretrieve(url_page, page.html) # 下载图片 # url_img https://img0.baidu.com/it/u647326367,1585486728fm253fmtautoapp120fJPEG?w500h653 # urllib.request.urlretrieve(urlurl_img, filename img3.jpg) # 下载视频 url_video https://vd9.bdstatic.com/mda-rhpq7j4xwp3ikjni/mb/cae_h264/1756055205656822141/mda-rhpq7j4xwp3ikjni.mp4?v_from_shkapp-haokan-nanjingauth_key1775598185-0-0-00c30dbe924b0d8c6cf688745691469dbcevod_channelsearchbox_feedpd1cr0cd0pt3logid2585762991vid17348459069101845158klogid2585762991abtest urllib.request.urlretrieve(url_video, video.mp4)视频下载地址的获取请求对象的定制UA介绍 :User Agent中文名为用户代理简称UA它是一个特殊字符串头使得服务器能够识别客户使用的操作系统及版本、cPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等直接请求看一下只能回来一部分数据, 因为http有ssl安全协议, 直接请求的时候缺少UA参数, 服务器识别为非浏览器请求这就是我们认识的第一种反爬手段, UA反爬import urllib.request url https://www.baidu.com headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 } response urllib.request.urlopen(url) content response.read().decode(utf-8) print(content)通过语法: request urllib.request.Request() 设置UA数据import urllib.request url https://www.baidu.com headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 } # 完整的参数列表是 url,data,headers, ... # 形参和实参位置不对应的时候要使用关键字传参, 就是headersheaders这种写法 request urllib.request.Request(url, headersheaders) response urllib.request.urlopen(request) content response.read().decode(utf-8) print(content)编解码单个参数编码 urllib.parse.quote()import urllib.request import urllib.parse # 1. 手动编码拼接参数 # 直接请求会报错, ascii codec cant encode characters in position 10-12: ordinal not in range(128) # url https://www.baidu.com/s?wd周杰伦 # 因为周杰伦是中文, 不在ascii编码范围内 # 编码会的请求是这样子 # https://www.baidu.com/s?wd%E5%91%A8%E6%9D%B0%E4%BC%A6 base_url https://www.baidu.com/s?wd headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 } # 使用 urllib.parse.quote() 进行unicode编码 new_url base_url urllib.parse.quote(周杰伦) print(new_url, new_url) request urllib.request.Request(urlnew_url, headersheaders) response urllib.request.urlopen(request) content response.read().decode(utf-8) print(content)复杂参数编码 urllib.parse.urlencode()import urllib.request import urllib.parse # 2. 自动编码拼接参数, 适合多参数/ base_url https://www.baidu.com/s? data { wd: 周杰伦, sex: 男, location: 中国 } data_code urllib.parse.urlencode(data) new_url base_url data_code print(new_url, new_url) headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 } # 设置请求对象 request urllib.request.Request(urlnew_url, headersheaders) # 模拟请求 response urllib.request.urlopen(request) content response.read().decode(utf-8) print(content)post请求的参数处理 urllib.parse.urlencode().encode(utf-8)import urllib.request import urllib.parse import json # 3.post请求的参数必须进行编码 base_url https://fanyi.baidu.com/sug headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 } data { kw: spider } # post请求的参数必须进行编码 data_code urllib.parse.urlencode(data).encode(utf-8) # 创建请求对象 request urllib.request.Request(urlbase_url, datadata_code, headersheaders) # 模拟请求 response urllib.request.urlopen(request) # 解析响应数据 content response.read().decode(utf-8) print(type(content)) # class str 类型 # 把json字符串转换成字典, 方便查看 obj json.loads(content) print(obj)总结post和get区别get请求方式的参数必须编码参数是拼接到url后面编码之后不需要调用encode方法post请求方式的参数必须编码参数是放在请求对象定制的方法中编码之后需要调用encode方法认识cookie百度详细翻译案例import urllib.request import urllib.parse url https://fanyi.baidu.com/v2transapi headers { Cookie: REALTIME_TRANS_SWITCH1; FANYI_WORD_SWITCH1; HISTORY_SWITCH1; SOUND_SPD_SWITCH1; SOUND_PREFER_SWITCH1; PSTM1537097513;BIDUPSIDD96F9A49A8630C54630DD60CE082A55C; BAIDUID0814C35D13AE23F5EAFA8E0B24D9B436:FG1;to_lang_often%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; from_lang_often%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; BDORZB490B5EBF6F3CD402E515D22BCDA1598;delPer0; H_PS_PSSID1424_21115_29522_29519_29099_29568_28835_29220_26350; PSINO2; ocalezhHm_lvt_64ecd82404c51e03dc91cb9e8c0255741563000604,1563334706,1565592510Hm_lpvt_64ecd82404c51e03dc91cb9e8c0255741565592510yjs_js_security_passport2379b52646498f3b5d216e6b21c6f1c7bf00f062_1565592544_js } data { from: en, to: zh, query: you, transtype: realtime, simple_means_flag: 3, sign: 269482.65435, token: 2e0f1cb44414248f3a2b49fbad28bbd5, } # 参数的编码 data urllib.parse.urlencode(data).encode(utf‐8) # 请求对象的定制 request urllib.request.Request(urlurl, headersheaders, datadata) response urllib.request.urlopen(request) # 请求之后返回的所有的数据 content response.read().decode(utf‐8) # loads将字符串转换为python对象 obj json.loads(content) # python对象转换为json字符串 ensure_asciiFalse 忽略字符集编码 s json.dumps(obj, ensure_asciiFalse) print(s)ajax的get请求案例: 豆瓣电影# 爬取豆瓣电影前10页数据 # https://movie.douban.com/j/chart/top_list?type20interval_id100%3A90actionstart0limit20 # https://movie.douban.com/j/chart/top_list?type20interval_id100%3A90actionstart20limit20 # https://movie.douban.com/j/chart/top_list?type20interval_id100%3A90actionstart40limit20 # 找规律 # page 1 2 3 4 # start 0 20 40 60 # start (page - 1) * 20 import urllib.request import urllib.parse def create_request(page): base_url https://movie.douban.com/j/chart/top_list?type20interval_id100%3A90action # 创建参数 data { start: (page - 1) * 20, limit: 20 } headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 } # 对参数进行编码 data urllib.parse.urlencode(data) # 拼接url url base_url data # 创建请求对象 request urllib.request.Request(urlurl, headersheaders) return request def get_content(request): response urllib.request.urlopen(request) content response.read().decode(utf‐8) return content def down_load(page, content): # with open文件的名字模式编码 as fp: # fp.write(内容) with open(data/douban_ str(page) .json, w, encodingutf‐8) as fp: fp.write(content) if __name__ __main__: for page in range(1, 11): # 创建请求对象 request create_request(page) # 请求数据 content get_content(request) # 保存数据 down_load(page, content)ajax的post请求案例: KFC# 1页 # http://www.kfc.com.cn/kfccda/ashx/GetStorelist.ashx?opcname # #post # cname:北京 # pid: # pageIndex: 1 # pagesize:10 # 2页 # http://www.kfc.com.cn/kfccda/ashx/GetStorelist.ashx?opcname # #post # cname:北京 # pid: # pageIndex: 2 # pagesize:10 import urllib.parse import urllib.request def create_request(page): base_url http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?opcname headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 } data { cname: 北京, pid: , pageIndex: page, pagesize: 10 } data urllib.parse.urlencode(data).encode(utf-8) request urllib.request.Request(urlbase_url, datadata, headersheaders) return request def get_content(request): response urllib.request.urlopen(request) content response.read().decode(utf-8) return content def down_load(page, content): with open(data/kfc_ str(page) .json, w, encodingutf-8) as fp: fp.write(content) if __name__ __main__: for page in range(1, 11): # 创建请求对象 request create_request(page) # 模拟请求 content get_content(request) # 保存数据 down_load(page, content)URLError\HTTPErrorHTTPError类是URLError类的子类导入的包urllib.error.HTTPError 或 urllib.error.URLErrorhttp错误: http错误是针对浏览器无法连接到服务器而增加出来的错误提示。引导并告诉浏览者该页是哪里出了问题。通过urllib发送请求的时候有可能会发送失败这个时候如果想让你的代码更加的健壮可以通过try except进行捕获异常异常有两类URLError/HTTPErrorimport urllib.request import urllib.error url https://mp.csdn.net/mp_blog/creation/editor/159887412 # url http://www.goudan11111.com headers { cookie: UNCSDN20221005; uuid_tt_dd163602-351516; fid20_96735975599-1762-486861; c_dls://so.csdn.net/so/search; _gaGA1.2.260231072.1760613870; _ga_7W1N0GEY1PGS2.1.s1765542085$o43$g0$t1765542085$j60$l0$h0; UserNameCSDN20221005; UserInfo0ce910cfa1124ec8bde573f352e0650c; UserToken0ce910cfa1124ec8bde573f352e0650c; UserNick%E5%BF%AB%E7%A0%81%E8%BD%AF%E4%BB%B6; AUB9E; BT1766363478052; p_uidU010000; c_dl_prid1769936316588_544489; c_dl_rid1769936342660_385249; c_dl_fpage/download/ashyyyy/91030805; c_dl_umdistribute.pc_search_result.none-task-c_download-2%7Eall%7EElasticCommercialInsert%7Esearch_v2-2-1anzdviqqk-null-null.142%5Ev102%5Epc_search_result_base6; c_ins_prid-; c_ins_rid1770014611135_541230; c_ins_frefhttps://www.csdn.net/; c_ins_fpage/index.html; c_ins_um-; ins_first_time1770014610934; csdn_newcert_CSDN202210051; c_ab_test1; FCCDCF%5Bnull%2Cnull%2Cnull%2Cnull%2Cnull%2Cnull%2C%5B%5B32%2C%22%5B%5C%2221681bce-275e-4845-9978-bbc037cc981e%5C%22%2C%5B1761633171%2C239000000%5D%5D%22%5D%5D%5D; FCNEC%5B%5B%22AKsRol_pP_GXVQvYpjLEplY9AeV5ENQLPA6J-xUDcveQt4VsEq-KJy5Ml6ls7lCULJC-vs6rJ8r-9HrwpuMcXkMZWyRkUJwxICFnNXXeaspGhZMA5Atr7XaDzi094OjB7DEfaMFIfthpyWuMkEIedvzDbakO_gojCA%3D%3D%22%5D%5D; __gadsIDea6a7d6b7d15ab06:T1748843494:RT1775460248:SALNI_MZPSJmIwp9W7mTxU89zLwbiOsBtAA; __gpiUID0000110f654eeef3:T1748843494:RT1775460248:SALNI_MbN5ctn7OBCsYjBuTy9ltxmFCt3vw; __eoiIDd177a950eb87817e:T1769927668:RT1775460248:SAA-AfjbOinB7IF6miwt2xOFp5ZhW; creative_btn_mp3; dc_sidcf4dd0485fe07aa408bbf4f99e84d82c; dc_session_id10_1775723383757.429230; c_first_refdefault; c_segment12; Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac1775586013,1775641301,1775685686,1775723384; HMACCOUNTE1ECC4AAB5140464; c-sidebar-collapse0; _clck1j2b4a1%5E2%5Eg52%5E0%5E1524; _clsk1r5hgju%5E1775723419348%5E2%5E0%5En.clarity.ms%2Fcollect; c_prefdefault; c_first_pagehttps%3A//blog.csdn.net/ityard/article/details/102646738; c_dsid11_1775723496099.453642; c_page_iddefault; c_refhttps%3A//blog.csdn.net/csdnnews/article/details/159979326%3Fspm%3D1000.2115.3001.5927; Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac1775723513; log_Id_view134; log_Id_click5; log_Id_pv14; dc_tostd7x1e, user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 } try: request urllib.request.Request(urlurl, headersheaders) response urllib.request.urlopen(request) content response.read().decode(utf‐8) print(content) except urllib.error.HTTPError as e: # 请求已经成功到达服务器但服务器返回了错误响应 print(HTTPError, e) except urllib.error.URLError as e: # URL 存在错误 print(URLError, e)cookie登录爬取微博个人信息页# 场景: 如何绕过登录, 获取页面数据 # cookie referer 可以应对60%的网站 import urllib.request url https://weibo.cn/6451491586/info headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36, # cookie中携带者身份信息, 可以访问任意页面, # 如果不带着cookie, 一般都会被重定向到登录页面, 有些网站的登录页面不是utf-8编码, 对新手造成困扰, 这也是一种小的反爬手段 cookie: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, # referer用于告诉服务器, 该请求是从哪个页面过来的, 一般用作图片放盗链 referer: https://weibo.cn/, } # 请求对象的定制 request urllib.request.Request(urlurl, headersheaders) # 模拟浏览器向服务器发送请求 response urllib.request.urlopen(request) # 获取响应的数据 content response.read().decode(utf-8) #将数据保存到本地 with open(weibo.html,w,encodingutf-8)as fp: fp.write(content)Handler处理器为什么要学习handler?urllib.request.urlopen(url) 不能定制请求头urllib.request.Request(url,headers,data) 可以定制请求头Handler定制更高级的请求头 , 随着业务逻辑的复杂, 请求对象的定制已经满足不了我们的需求动态cookie和代理技术需要Handler基础语法# 需求 使用handler来访问百度 获取网页源码 import urllib.request url http://www.baidu.com headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 } request urllib.request.Request(url url,headers headers) # 核心步骤 # handler build_opener open # 1获取hanlder对象 handler urllib.request.HTTPHandler() # 2获取opener对象 opener urllib.request.build_opener(handler) # (3) 调用open方法 response opener.open(request) content response.read().decode(utf-8) print(content)代理服务器代理的常用功能?突破自身IP访问限制访问国外站点。访问一些单位或团体内部资源某大学FTP(前提是该代理地址在该资源的允许访问范围之内)使用教育网内地址段免费代理服务器就可以用于对教育网开放的各类FTP下载上传以及各类资料查询共享等服务。提高访问速度扩展: 通常代理服务器都设置一个较大的硬盘缓冲区当有外界的信息通过时同时也将其保存到缓冲区中当其他用户再访问相同的信息时则直接由缓冲区中取出信息传给用户以提高访问速度。隐藏真实IP扩展: 上网者也可以通过这种方法隐藏自己的IP免受攻击。代码配置代理创建Reuqest对象创建ProxyHandler对象用handler对象创建opener对象使用opener.open函数发送请求免费的代理:代码示例import urllib.request url http://www.baidu.com/s?wdip headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 } # 请求对象的定制 request urllib.request.Request(url url,headers headers) # 不使用代理的话就直接发送请求了 # response urllib.request.urlopen(request) proxies { # http:118.24.219.151:16817, http:114.231.172.127:22710 } # handler build_opener open handler urllib.request.ProxyHandler(proxies proxies) opener urllib.request.build_opener(handler) response opener.open(request) # 获取响应的信息 content response.read().decode(utf-8) # 保存 with open(data/daili.html,w,encodingutf-8)as fp: fp.write(content)代理池import urllib.request proxies_pool [ {http:118.24.219.151:16817}, {http:221.227.180.231:18620}, ] import random proxies random.choice(proxies_pool) url http://www.baidu.com/s?wdip headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 } request urllib.request.Request(url url,headersheaders) handler urllib.request.ProxyHandler(proxiesproxies) opener urllib.request.build_opener(handler) response opener.open(request) content response.read().decode(utf-8) with open(daili.html,w,encodingutf-8)as fp: fp.write(content)