关于requests:HTTP请求requests的进阶使用方法浅析-京东云技术团队

1 背景上篇文章解说了requests模块的根底应用,其中有get、put、post等多种申请形式,应用data、json等格局做为申请参数,在申请体中增加申请头部信息的常见信息,如:headers、cookies,以及对申请响应的解决办法。接下来解说一下requests的高级用法。 2 进阶办法举例2.1 requests.request()method:提交形式(get|post); url:提交地址; kwargs:14个管制拜访的参数; []() 罕用的参数有:params、data、json、headers、cookies,已在上篇文章中介绍过了,感兴趣的敌人,能够到上篇文章再回顾一下。以下将解说与示例其余参数的应用。 示例: 2.1.1 files申请携带文件,如果有的申请须要上传文件,能够用它来实现。 import requests# 上传文件f= {"files": open("favicon.ico", "rb") }data = {"name": "上传文件"}requests.request( method = 'POST', url = 'http://127.0.0.1:8080/example/request', data = data, files = f)需注意:favicon.ico文件需和以后脚本在同一目录下,如果不在,能够将文件名称批改为文件门路 import requestsfrom requests.auth import HTTPBasicAuth, HTTPDigestAuth# 1、Basic Auth认证res = requests.request( method = 'GET', url = 'http://127.0.0.1:8080/example/request', auth = HTTPBasicAuth("username", "password"))res.encoding = "gbk"print(res.status) # 200# 2、DIGEST 认证res = requests.request( method = 'GET', url = 'http://127.0.0.1:8080/example/request', auth = HTTPDigestAuth("username", "password"))res.encoding = "gbk"print(res.status) # 200http auth认证的两种形式,别离为Basic形式和Digest认证,其中:Basic Auth的长处是提供简略的用户验证性能,其认证过程简单明了,适宜于对安全性要求不高的零碎或设施中;同样存在毛病:输出的用户名,明码 base64编码后会呈现在Authorization里,很容易被解析进去。 ...

June 16, 2023 · 3 min · jiezi

关于requests:PythonRequests零基础系统掌握接口自动化测试晨兴理荒秽带月荷锄归

download:Python+Requests零根底零碎把握接口自动化测试Requests是一个用于发送HTTP申请的Python库。它能够让开发人员不便地解决网络申请,并且反对多种HTTP办法,包含GET、POST、PUT、DELETE等。上面咱们将深刻理解Requests库,并理解它的根本用法和一些罕用性能。 装置Requests在开始应用Requests之前,须要先装置它。能够通过以下命令来装置: Copy codepip install requests装置实现之后,咱们就能够开始应用Requests了。 发送HTTP申请应用Requests发送HTTP申请非常简单。咱们只须要构建一个申请对象,而后调用相应的办法即可。例如,要发送一个GET申请,能够应用以下代码: pythonCopy codeimport requests response = requests.get('http://www.example.com') print(response.text)这段代码将发送一个GET申请到http://www.example.com,并将响应内容打印进去。同样的,咱们也能够应用其余HTTP办法来发送申请,例如POST、PUT、DELETE等。 响应解决当咱们发送一个HTTP申请之后,服务器会返回一个响应。应用Requests库,咱们能够轻松地解决这个响应。例如,咱们能够获取响应的状态码、头信息和内容等。以下是一个获取响应状态码的例子: pythonCopy codeimport requests response = requests.get('http://www.example.com') print(response.status_code)这段代码将发送一个GET申请到http://www.example.com,并输入响应的状态码。同样的,咱们也能够获取响应的头信息、响应内容等。 申请参数有时候咱们须要向服务器发送一些参数,例如查问参数或表单数据等。应用Requests库,咱们能够不便地构建这些参数并发送给服务器。以下是一个发送查问参数的例子: pythonCopy codeimport requests payload = {'key1': 'value1', 'key2': 'value2'} response = requests.get('http://www.example.com', params=payload) print(response.text)这段代码将发送一个带有查问参数的GET申请到http://www.example.com,并输入响应内容。同样的,咱们也能够发送POST申请并传递表单数据。 Cookie在Web应用程序中,cookie是一种常见的身份验证形式。应用Requests库,咱们能够不便地解决cookie。以下是一个获取cookie的例子: pythonCopy codeimport requests response = requests.get('http://www.example.com') cookies = response.cookies print(cookies)这段代码将发送一个GET申请到并获取响应的cookie。同样的,咱们也能够将cookie发送到服务器端。 会话治理在Web应用程序中,有时候须要放弃与服务器的长期会话。应用Requests库,咱们能够不便地治理这些会话。以下是一个应用会话对象的例子: pythonCopy codeimport requests session = requests.Session() session.get('http://www.example.com/login', data={'username': 'user', 'password': 'pass'}) response = session.get('http://www.example.com/protected_page') print(response.text)这段代码将创立一个会话对象,并应用它

April 10, 2023 · 1 min · jiezi

关于requests:还在用requests写爬虫吗这个库效率提高一倍

最近公司  Python 后端我的项目进行重构,整个后端逻辑根本都变更为采纳"异步"协程的形式实现。看着满屏幕通过 async await(协程在 Python 中的实现)润饰的代码,我登时感到一脸懵逼,手足无措。 尽管之前有理解过"协程"是什么货色,但并没有深刻摸索,于是正好借着这次机会能够好好学习一下。 什么是协程?简略来说,协程是一种基于线程之上,但又比线程更加轻量级的存在。对于零碎内核来说,协程具备不可见的个性,所以这种由 程序员本人写程序来治理 的轻量级线程又常被称作 "用户空间线程"。 协程比多线程好在哪呢?线程的控制权在操作系统手中,而 协程的控制权齐全把握在用户本人手中,因而利用协程能够缩小程序运行时的上下文切换,无效进步程序运行效率。建设线程时,零碎默认调配给线程的 栈 大小是 1 M,而协程更轻量,靠近 1 K 。因而能够在雷同的内存中开启更多的协程。因为协程的实质不是多线程而是单线程,所以不须要多线程的锁机制。因为只有一个线程,也不存在同时写变量而引起的抵触。在协程中管制共享资源不须要加锁,只须要判断状态即可。所以协程的执行效率比多线程高很多,同时也无效防止了多线程中的竞争关系。协程的实用 & 不实用场景实用场景:协程实用于被阻塞的,且须要大量并发的场景。 不实用场景:协程不适用于存在大量计算的场景(因为协程的实质是单线程来回切换),如果遇到这种状况,还是应该应用其余伎俩去解决。 初探异步 http 框架 httpx至此咱们对 "协程" 应该有了个大略的理解,但故事说到这里,置信有敌人还是满脸疑难:"协程" 对于接口测试有什么帮忙呢?不要焦急,答案就在上面。 置信用过 Python 做接口测试的敌人都对 requests 库不生疏。requests 中实现的 http 申请是同步申请,但其实基于 http 申请 IO 阻塞的个性,非常适合用协程来实现 "异步" http 申请从而晋升测试效率。 置信早就有人留神到了这点,于是在 Github 通过了一番摸索后,果不其然,最终寻找到了反对协程 "异步" 调用 http 的开源库: httpx 什么是 httpxhttpx 是一个简直继承了所有 requests 的个性并且反对 "异步" http 申请的开源库。简略来说,能够认为 httpx 是强化版 requests。 上面大家能够跟着我一起见识一下 httpx 的弱小 装置httpx 的装置非常简单,在 Python 3.6 以上的环境执行 ...

July 20, 2022 · 2 min · jiezi

Python3微信公众平台模拟登陆

声明此代码仅供技术交流学习,擅自用于其他,一切后果与本人无关目标网址: https://mp.weixin.qq.com/ 所谓模拟登陆,就是自己模拟构造请求发送给服务器,然后服务器返回认证的信息过来,当然这个其中的交互过程稍微有点复杂,可能不止一次的交互。我们这次模拟登陆成功的标志就是拿到登陆后的token和cookie, cookie有过期时间,我稍微测试了下大概有10个小时左右。 效果图按照管理首先摆上效果图,证明我这个代码目前是真是可以运行的。代码文末附上!图一:是完整登陆后的过程,打印出来了token 和 cookie, 这是演示代码,实际可以存储起来到redis或者其他地方。 图二:这是验证tokne和cookie是否有用,由于我的公众号就只发了一遍测试文章,内容啥的都没有,所有拿到的json数据很少,但是总的来说是可以的 思路分析由于这个代码是我很早写的,所以思路就没有图文对照,懒得再去截图演示了,但是上面两个效果图是我写博客的时候又重写运行过一遍的,目前是有效的。 1 首先一般的步骤都是打开Chrome浏览器,打开网址,然后f12 找到 填写账号密码的from表单之类的,但是这个套路针对此次模拟行不通。因为微信公众平台老是跳转刷新,所以很难找到请求的网址和接口。2 所以我们换个思路,其实我们可以打开网页后用抓包工具看各种请求的接口和跳转情况。我们先在浏览器打开网址,然后打开fiddler或者charles 等抓包工具,不会抓包工具的,这里不讲,自己去找找相关资料,安装使用不难,就是有点繁琐。 3 分析结果的过程不难,照着登陆流程走,反复调试就可以。好的,现在就是代码地址:https://github.com/wgPython/w... 如果对你有帮助,麻烦点下star!!毕竟写博客都是义务操作。

July 5, 2019 · 1 min · jiezi

pythonrequests爬取知乎个人信息数据

效果预览地址:http://23.105.208.123/ 技术栈python3requestsredisechart源码地址https://github.com/MasakiOvO/... python需要安装的库requests,BeautifulSoup,redis,django 思路两个程序。 一个程序负责爬取用户关注和粉丝列表, 并把用户名存入set另一个程序负责根据用户名获取详细信息,存入hash维护 两个列表 1.已爬用户 2.未爬用户第一个程序的流程: 当未爬set不为空时:执行如下操作:每次从未爬取列表中取出一个用户名 根据用户名,获取他的关注与粉丝并遍历,如果用户既没在已爬用户,也没在未爬用户 加入未爬用户列表。第二个程序的流程 每次从未爬set中取出一个用户名,调用接口获取详细信息并存入redis hash中接口获取打开某个人的个人主页,按F12 选择XHR 然后点击图1的关注我的人,和我关注的人,在图2就可以看到header和cookie。 获取用户列表Api: https://www.zhihu.com/api/v4/...{username}/{type}?include=data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics&offset=20&limit=20username 是用户名, type 是类型, 有两种可选 [followers,followees], followers是粉丝 followees是关注改变offset的值可以获取分页 获取个人信息Api: https://www.zhihu.com/people/...user_token是用户名这个api中 返回的是html页面,在html页面中有一个scirpt标签里面的内容是json格式的用户信息,这就很方便了,直接获取键值对 对应的属性就ok。 发送请求F12查看接口,把header和cookie放进requests.get()方法中。 剩下的就很简单了,不赘述了。 总结还有很多优化的地方。比如加入中间件,来提升爬虫的稳定性。对数据进行分类,统计城市分布。

June 27, 2019 · 1 min · jiezi

OverflowError-string-longer-than-2147483647-bytes-问题

问题简述使用python requests上传文件时, 报OverflowError: string longer than 2147483647 bytes 错误. detail问题代码 data = {} with open("bigfile", "rb") as f: r = requests.post(PUBLISH_URL, data=data, files={"xxx": f})tracebackTraceback (most recent call last): File "test.py", line 52, in <module> main() File "test.py", line 49, in main publish() File "test.py", line 41, in publish r = requests.post(PUBLISH_URL, data=cfg, files={file_key: ("./test.apk", f)}) File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 116, in post return request('post', url, data=data, json=json, **kwargs) File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 60, in request return session.request(method=method, url=url, **kwargs) File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 533, in request resp = self.send(prep, **send_kwargs) File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 646, in send r = adapter.send(request, **kwargs) File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 449, in send timeout=timeout File "/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py", line 600, in urlopen chunked=chunked) File "/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py", line 354, in _make_request conn.request(method, url, **httplib_request_kw) File "/usr/lib/python2.7/httplib.py", line 1057, in request self._send_request(method, url, body, headers) File "/usr/lib/python2.7/httplib.py", line 1097, in _send_request self.endheaders(body) File "/usr/lib/python2.7/httplib.py", line 1053, in endheaders self._send_output(message_body) File "/usr/lib/python2.7/httplib.py", line 897, in _send_output self.send(msg) File "/usr/lib/python2.7/httplib.py", line 873, in send self.sock.sendall(data) File "/usr/lib/python2.7/ssl.py", line 743, in sendall v = self.send(data[count:]) File "/usr/lib/python2.7/ssl.py", line 709, in send v = self._sslobj.write(data)OverflowError: string longer than 2147483647 bytes分析过程requests 将file obj 全部读入内存了没想到requests的实现这么粗暴, 直接file.read(), 实际也是如此, 发送大文件时, 内存快速上涨. 代码如下:requests/models.py ...

April 25, 2019 · 3 min · jiezi

python三方库之requests-快速上手

基于2.21.0发送请求发送GET请求:r = requests.get(‘https://api.github.com/events')发送POST请求:r = requests.post(‘https://httpbin.org/post', data={‘key’:‘value’})其他请求接口与HTTP请求类型一致,如PUT, DELETE, HEAD, OPTIONS等。在URL查询字符串中使用参数给params参数传递一个字典对象:>>> payload = {‘key1’: ‘value1’, ‘key2’: ‘value2’}>>> r = requests.get(‘https://httpbin.org/get', params=payload)>>> print(r.url)https://httpbin.org/get?key2=value2&key1=value1字典的值也可以是一个列表:>>> payload = {‘key1’: ‘value1’, ‘key2’: [‘value2’, ‘value3’]}>>> r = requests.get(‘https://httpbin.org/get', params=payload)>>> print(r.url)https://httpbin.org/get?key1=value1&key2=value2&key2=value3参数中值为None的键值对不会加到查询字符串文本响应内容Response对象的text属性可以获取服务器响应内容的文本形式,Requests会自动解码:>>> r = requests.get(‘https://api.github.com/events')>>> r.text’[{“id”:“9167113775”,“type”:“PushEvent”,“actor”…访问Response.text时,Requests将基于HTTP头猜测响应内容编码。使用Response.encoding属性可以查看或改变Requests使用的编码:>>> r.encoding’utf-8’>>> r.encoding = ‘ISO-8859-1’二进制响应内容Response对象的content属性可以获取服务器响应内容的二进制形式:>>> r.contentb’[{“id”:“9167113775”,“type”:“PushEvent”,“actor”…JSON响应内容Response对象的json()方法可以获取服务器响应内容的JSON形式:>>> r = requests.get(‘https://api.github.com/events’)>>> r.json()[{‘repo’: {‘url’: ‘https://api.github.com/…如果JSON解码失败,将抛出异常。原始响应内容在极少情况下,可能需要访问服务器原始套接字响应。通过在请求中设置stream=True参数,并访问Response对象的raw属性实现:>>> r = requests.get(‘https://api.github.com/events’, stream=True)>>> r.raw<urllib3.response.HTTPResponse object at 0x101194810>>>> r.raw.read(10)’\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03’通常的用法是用下面这种方式将原始响应内容保存到文件,Response.iter_content方法将自动解码gzip和deflate传输编码:with open(filename, ‘wb’) as fd: for chunk in r.iter_content(chunk_size=128): fd.write(chunk)定制请求头传递一个dict对象到headers参数,可以添加HTTP请求头:>>> url = ‘https://api.github.com/some/endpoint’>>> headers = {‘user-agent’: ‘my-app/0.0.1’}>>> r = requests.get(url, headers=headers)定制的header的优先级较低,在某些场景或条件下可能被覆盖。所有header的值必须是string, bytestring或unicode类型。但建议尽量避免传递unicode类型的值更复杂的POST请求发送form-encoded数据给data参数传递一个字典对象:>>> payload = {‘key1’: ‘value1’, ‘key2’: ‘value2’}>>> r = requests.post(“https://httpbin.org/post”, data=payload)如果有多个值对应一个键,可以使用由元组组成的列表或者值是列表的字典:>>> payload_tuples = [(‘key1’, ‘value1’), (‘key1’, ‘value2’)]>>> r1 = requests.post(‘https://httpbin.org/post’, data=payload_tuples)>>> payload_dict = {‘key1’: [‘value1’, ‘value2’]}>>> r2 = requests.post(‘https://httpbin.org/post’, data=payload_dict)发送非form-encoded数据如果传递的是字符串而非字典,将直接发送该数据:>>> import json>>> url = ‘https://api.github.com/some/endpoint’>>> payload = {‘some’: ‘data’}>>> r = requests.post(url, data=json.dumps(payload))或者可以使用json参数自动对字典对象编码:>>> url = ‘https://api.github.com/some/endpoint’>>> payload = {‘some’: ‘data’}>>> r = requests.post(url, json=payload)a) 如果在请求中使用了data或files参数,json参数会被忽略。b) 在请求中使用json参数会改变Content-Type的值为application/jsonPOST一个多部分编码(Multipart-Encoded)的文件上传文件:>>> url = ‘https://httpbin.org/post’>>> files = {‘file’: open(‘report.xls’, ‘rb’)}>>> r = requests.post(url, files=files)显式地设置文件名,内容类型(Content-Type)以及请求头:>>> url = ‘https://httpbin.org/post’>>> files = {‘file’: (‘report.xls’, open(‘report.xls’, ‘rb’), ‘application/vnd.ms-excel’, {‘Expires’: ‘0’})}>>> r = requests.post(url, files=files)甚至可以发送作为文件接收的字符串:>>> url = ‘http://httpbin.org/post’>>> files = {‘file’: (‘report.csv’, ‘some,data,to,send\nanother,row,to,send\n’)}>>> r = requests.post(url, files=files)如果发送的文件过大,建议使用第三方包requests-toolbelt做成数据流。强烈建议以二进制模式打开文件,因为Requests可能以文件中的字节长度来设置Content-Length响应状态码Response对象的status_code属性可以获取响应状态:>>> r = requests.get(‘https://httpbin.org/get’)>>> r.status_code200requests库还内置了状态码以供参考:>>> r.status_code == requests.codes.okTrue如果请求异常(状态码为4XX的客户端错误或5XX的服务端错误),可以调用raise_for_status()方法抛出异常:>>> bad_r = requests.get(‘https://httpbin.org/status/404’)>>> bad_r.status_code404>>> bad_r.raise_for_status()Traceback (most recent call last): File “requests/models.py”, line 832, in raise_for_status raise http_errorrequests.exceptions.HTTPError: 404 Client Error响应头Response对象的headers属性可以获取响应头,它是一个字典对象,键不区分大小写:>>> r.headers{ ‘content-encoding’: ‘gzip’, ’transfer-encoding’: ‘chunked’, ‘connection’: ‘close’, ‘server’: ’nginx/1.0.4’, ‘x-runtime’: ‘148ms’, ’etag’: ‘“e1ca502697e5c9317743dc078f67693f”’, ‘content-type’: ‘application/json’}>>> r.headers[‘Content-Type’]‘application/json’>>> r.headers.get(‘content-type’)‘application/json’CookiesResponse对象的cookies属性可以获取响应中的cookie信息:>>> url = ‘http://example.com/some/cookie/setting/url’>>> r = requests.get(url)>>> r.cookies[’example_cookie_name’]’example_cookie_value’使用cookies参数可以发送cookie信息:>>> url = ‘https://httpbin.org/cookies’>>> cookies = dict(cookies_are=‘working’)>>> r = requests.get(url, cookies=cookies)Response.cookies返回的是一个RequestsCookieJar对象,跟字典类似但提供了额外的接口,适合多域名或多路径下使用,也可以在请求中传递:>>> jar = requests.cookies.RequestsCookieJar()>>> jar.set(’tasty_cookie’, ‘yum’, domain=‘httpbin.org’, path=’/cookies’)>>> jar.set(‘gross_cookie’, ‘blech’, domain=‘httpbin.org’, path=’/elsewhere’)>>> url = ‘https://httpbin.org/cookies’>>> r = requests.get(url, cookies=jar)>>> r.text’{“cookies”: {“tasty_cookie”: “yum”}}‘重定向及请求历史requests默认对除HEAD外的所有请求执行地址重定向。Response.history属性可以追踪重定向历史,它返回一个list,包含为了完成请求创建的所有Response对象并由老到新排序。下面是一个HTTP重定向HTTPS的用例:>>> r = requests.get(‘http://github.com/’)>>> r.url’https://github.com/’>>> r.status_code200>>> r.history[<Response [301]>]使用allow_redirects参数可以禁用重定向:>>> r = requests.get(‘http://github.com/’, allow_redirects=False)>>> r.status_code301>>> r.history[]如果使用的是HEAD请求,也可以使用allow_redirects参数允许重定向:>>> r = requests.head(‘http://github.com/’, allow_redirects=True)>>> r.url’https://github.com/’>>> r.history[<Response [301]>]请求超时使用timeout参数设置服务器返回响应的最大等待时间:>>> requests.get(‘https://github.com/’, timeout=0.001)Traceback (most recent call last): File “<stdin>”, line 1, in <module>requests.exceptions.Timeout: HTTPConnectionPool(host=‘github.com’, port=80): Request timed out. (timeout=0.001)错误及异常ConnectionError:网络异常,比如DNS错误,连接拒绝等。HTTPError:如果请求返回4XX或5XX状态码,调用Response.raise_for_status()会抛出此异常。Timeout:连接超时。TooManyRedirects:请求超过配置的最大重定向数。RequestException:异常基类。 ...

March 4, 2019 · 2 min · jiezi

weekly 2019-02-15

我开始学习Python了,这样我可以用它作为后端语言来学,也可以用来刷Leetcode,学爬虫等等这周我学习了:Python基础语法BeautiuilSoup Request库学习记录在这里 前期语法还不熟,慢慢来,有空就刷刷题

February 15, 2019 · 1 min · jiezi

爬取百度热点新闻排行榜

import requestsfrom bs4 import BeautifulSoupdef get_html(url,headers): r = requests.get(url,headers=headers) r.encoding = r.apparent_encoding return r.textdef get_pages(html): soup = BeautifulSoup(html,‘html.parser’) all_topics=soup.find_all(’tr’)[1:] for each_topic in all_topics: topic_times = each_topic.find(’td’, class_=‘last’) # 搜索指数 topic_rank = each_topic.find(’td’, class_=‘first’) # 排名 topic_name = each_topic.find(’td’, class_=‘keyword’) # 标题目 if topic_rank != None and topic_name != None and topic_times != None: topic_rank = each_topic.find(’td’, class_=‘first’).get_text().replace(’ ‘, ‘’).replace(’\n’, ‘’) topic_name = each_topic.find(’td’, class_=‘keyword’).get_text().replace(’ ‘, ‘’).replace(’\n’, ‘’) topic_times = each_topic.find(’td’, class_=‘last’).get_text().replace(’ ‘, ‘’).replace(’\n’, ‘’) # print(‘排名:{},标题:{},热度:{}’.format(topic_rank,topic_name,topic_times)) tplt = “排名:{0:^4}\t标题:{1:{3}^15}\t热度:{2:^8}” print(tplt.format(topic_rank, topic_name, topic_times, chr(12288)))def main(): #百度热点排行榜单链接 url = ‘http://top.baidu.com/buzz?b=1&fr=20811' headers = {‘User-Agent’: ‘Mozilla/5.0’} html = get_html(url, headers) get_pages(html)if name == ‘main’: main() ...

January 16, 2019 · 1 min · jiezi

python爬虫-requests与bs4获得所有炉石传说卡背

太简单了就当做个记录,直接贴代码了import osimport requestsfrom bs4 import BeautifulSoupimport time# 发送请求def send(): r = requests.get(url=base_url) # 设置编码防止乱码 r.encoding =“GBK”; content = r.text parseAndSave(content)# 解析页面和保存数据def parseAndSave(html): soup = BeautifulSoup(html, ’lxml’) ulList = soup.find_all(‘ul’, attrs={‘class’: ‘kzlist’}) # print(ulList); for ul in ulList: li = ul.find_all(’li’); for item in li: name = item.find(‘img’).next_sibling obtain_method = item.find(‘a’).find(‘p’).text rootDir = os.getcwd() if not os.path.exists(name): os.mkdir(name); os.chdir(name); src = item.find(‘a’).find(‘img’)[‘src’] pic = requests.get(src) with open(‘pic.jpg’, ‘wb’) as fw: fw.write(pic.content) with open(‘info.txt’, ‘a+’) as fw: fw.write(name+’\n’) fw.write(obtain_method) os.chdir(rootDir);def main(): start_time = time.time() send() end_time = time.time() print(‘程序用时:’,(end_time - start_time))if name == ‘main’: base_url = ‘http://news.4399.com/gonglue/lscs/kabei/' cardList = [] main() ...

January 2, 2019 · 1 min · jiezi

Python3爬取英雄联盟英雄皮肤大图

前言上篇文章,说到了,爬取LOL英雄皮肤的高清图片,最近有事,也没怎么去研究,所以,现在才去看了下,并且写了Python脚本来抓取皮肤图片。需要说明一下,这个脚本有部分英雄没有抓取到,但是具体原因,我目前还没搞懂,我是相当纳闷的。大家有兴趣的,可以看看后面遗留问题,一起研究下。爬虫思路初步尝试我先查看了network,并没有发现有可用的API;然后又用bs4去分析英雄列表页,但是请求到html里面,并没有英雄列表,在英雄列表的节点上,只有“正在加载中”这样的字样;同样的方法,分析英雄详情也是这种情况,所以我猜测,这些数据应该是Javascript负责加载的。继续尝试然后我就查看了英雄列表的源代码,查看外部引入的js文件,以及行内的js脚本,大概在368行,发现了有处理英雄列表的js注释,然后继续往下读这些代码,发现了第一个彩蛋,也就是他引入了一个champion.js的文件,我猜测,这个应该就是英雄列表大全了,然后我打开了这个链接的js,一眼看过去,黑麻麻一片,然后格式化了一下压缩的js,确定这就是英雄列表的js数据文件了。接着尝试前面通过查看列表的源代码,找到了英雄列表的js数据文件,那么,我继续随机点开了一个英雄的详情,然后查看英雄详情源代码,然后大概在568行看到有一个showSkin的js方法,通过这里,发现了第二个彩蛋,也就是皮肤图片的URL地址拼接方法。最后尝试上面找到了皮肤图片URL的拼接方法,并且发现了一行很关键的代码var skin =LOLherojs.champion[heroid].data.skins,也就是,这个skin变量,就是英雄皮肤的所有图片数组,但是这个文件内,并没有LOLherojs这个变量,也就是外部引入的,所以,需要继续查看下面的源代码,找到引入这个变量的位置,果不其然,在757行,发现了最后一个彩蛋,也就是,英雄皮肤的js文件,通过这里可以知道,每个英雄都有一个单独的js文件,并且知道了这个js文件的URL拼接方法。思路总结通过上面的分析,我们就得到了爬取LOL皮肤图片的所有数据准备了,也就是,直接,只需要提取js中的英雄列表以及英雄详情数据,就可实现我们的需求了。下面是运行后抓取到的图片……运行环境Python运行环境:python3.6 用到的模块:requests、json、urllib、os 未安装的模块,请使用pip instatll进行安装,例如:pip install requests完整代码其他啥的废话就不多说了,直接上完整代码,有问题,直接留言给我就行,另外,代码已上传GitHub。再说明一下,那些有问题的英雄详情的js文件,大家有时间也可以琢磨下,或者有其他的更加快捷的爬取这些图片的方法,也可以拿出来交流和讨论,谢谢。#!/usr/bin/env python# -- coding: utf-8 --“““抓取英雄联盟英雄全皮肤author: gxcuizydate: 2018-11-13"““import requestsimport jsonfrom urllib import parseimport osclass GetLolSkin(object): “““抓取LOL英雄皮肤””” def init(self): “““初始化变量””” self.hero_url = ‘https://lol.qq.com/biz/hero/champion.js' self.hero_detail_url = ‘http://lol.qq.com/biz/hero/' self.skin_folder = ‘skin’ self.skin_url = ‘https://ossweb-img.qq.com/images/lol/web201310/skin/big' @staticmethod def get_html(url): “““下载html””” request = requests.get(url) request.encoding = ‘gbk’ if request.status_code == 200: return request.text else: return “{}” def get_hero_list(self): “““获取英雄的完整信息列表””” hero_js = self.get_html(self.hero_url) # 删除左右的多余信息,得到json数据 out_left = “if(!LOLherojs)var LOLherojs={};LOLherojs.champion=” out_right = ‘;’ hero_list = hero_js.replace(out_left, ‘’).rstrip(out_right) return json.loads(hero_list) def get_hero_info(self, hero_id): “““获取英雄的详细信息””” # 获取js详情 detail_url = parse.urljoin(self.hero_detail_url, hero_id + ‘.js’) detail_js = self.get_html(detail_url) # 删除左右的多余信息,得到json数据 out_left = “if(!herojs)var herojs={champion:{}};herojs[‘champion’][%s]=” % hero_id out_right = ‘;’ hero_info = detail_js.replace(out_left, ‘’).rstrip(out_right) return json.loads(hero_info) def download_skin_list(self, skin_list, hero_name): “““下载皮肤列表””” # 循环下载皮肤 for skin_info in skin_list: # 拼接图片名字 if skin_info[’name’] == ‘default’: skin_name = ‘默认皮肤’ else: if ’ ’ in skin_info[’name’]: name_info = skin_info[’name’].split(’ ‘) skin_name = name_info[0] else: skin_name = skin_info[’name’] hero_skin_name = hero_name + ‘-’ + skin_name + ‘.jpg’ self.download_skin(skin_info[‘id’], hero_skin_name) def download_skin(self, skin_id, skin_name): “““下载皮肤图片””” # 下载图片 img_url = self.skin_url + skin_id + ‘.jpg’ request = requests.get(img_url) if request.status_code == 200: print(‘downloading……%s’ % skin_name) img_path = os.path.join(self.skin_folder, skin_name) with open(img_path, ‘wb’) as img: img.write(request.content) else: print(‘img error!’) def make_folder(self): “““初始化,创建图片文件夹””” if not os.path.exists(self.skin_folder): os.mkdir(self.skin_folder) def run(self): # 获取英雄列表信息 hero_json = self.get_hero_list() hero_keys = hero_json[‘keys’] # 循环遍历英雄 for hero_id, hero_code in hero_keys.items(): hero_name = hero_json[‘data’][hero_code][’name’] hero_info = self.get_hero_info(hero_id) if hero_info: skin_list = hero_info[‘result’][hero_id][‘skins’] # 下载皮肤 self.download_skin_list(skin_list, hero_name) else: print(‘英雄【%s】的皮肤获取有问题……’ % hero_name)# 程序执行入口if name == ‘main’: lol = GetLolSkin() # 创建图片存储文件 lol.make_folder() # 执行脚本 lol.run() ...

November 14, 2018 · 2 min · jiezi

Python爬取王者荣耀英雄皮肤高清图片

前言临下班前,看到群里有人在讨论用王者农药的一些皮肤作为电脑的壁纸,什么高清的,什么像素稍低的,网上查了一手,也有,但像素都不一样,所以,我就想着,自己去官网直接爬他的高清皮肤就好了,然后就有了这边文章说的主题了。爬图思路找到英雄列表进入官网,然后进入英雄介绍,查看更多英雄,就能看到全部的英雄了,也就是下面的这个链接英雄列表:https://pvp.qq.com/web201605/herolist.shtml英雄详情点击每个英雄进来,就可以看到每个英雄的详细信息,基本介绍以及皮肤展示,而我们需要爬取的皮肤,就在右下角那里,鼠标放上去,就可以逐个展示该皮肤了小鲁班的详细信息:https://pvp.qq.com/web201605/herodetail/112.shtml分析皮肤图片URL从上面的这张鲁班的图片中我们可以看到,通过F12定位到皮肤的小图片位置,li元素里有一个img的元素,其中img的src和data-imgname这两个属性,查看一下,就不难知道,src的属性值是小图,而data-imgname则是我们需要的大图URL,但是查看源码,就会发现,在html中,并没有这个属性,所以,需要我们分析这个URL的规律来得到其他英雄的皮肤图片,分析也不难发现,112就是英雄的id,而bigskin-2里面的2即表示这个英雄的第几张皮肤图片开始编写爬虫脚本第一步:定义一些常用变量第二步:抓取所有英雄列表第三步:循环遍历,分析每个英雄皮肤节点第四步:下载图片第五步:爬虫结束完整源码感觉上面七七八八的,说了些啥呀,真是墨迹,还不如直接上代码实在,好吧,我错了,马上交出源码,请各位看官饶恕,同时,代码我也上传了交友网站GitHub。#!/usr/bin/env python# -- coding: utf-8 --“““抓取王者荣耀皮肤author: gxcuizydate: 2018-11-06"““import requestsfrom bs4 import BeautifulSoupfrom urllib import parseimport osclass Skin(object): def init(self): # 英雄的json数据 self.hero_url = ‘https://pvp.qq.com/web201605/js/herolist.json' # 英雄详细页的通用url前缀信息 self.base_url = ‘https://pvp.qq.com/web201605/herodetail/' # 英雄详细页url后缀信息 self.detail_url = ’’ # 图片存储文件夹 self.img_folder = ‘skin’ # 图片url的通用前缀 self.skin_url = ‘https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/' # 图片url的后缀信息 self.skin_detail_url = ’’ def get_hero(self): “““获取英雄的json数据””” request = requests.get(self.hero_url) hero_list = request.json() return hero_list def get_hero_skin(self, hero_name, hero_no): “““获取详细页英雄皮肤展示的信息,并爬图””” url = parse.urljoin(self.base_url, self.detail_url) request = requests.get(url) request.encoding = ‘gbk’ html = request.text # 获取皮肤信息的节点 soup = BeautifulSoup(html, ’lxml’) skip_list = soup.select(’.pic-pf-list3’) for skin_info in skip_list: # 获取皮肤名称 img_names = skin_info.attrs[‘data-imgname’] name_list = img_names.split(’|’) skin_no = 1 # 循环下载皮肤图片 for skin_name in name_list: self.skin_detail_url = ‘%s/%s-bigskin-%s.jpg’ % (hero_no, hero_no, skin_no) skin_no += 1 img_name = hero_name + ‘-’ + skin_name + ‘.jpg’ self.download_skin(img_name) def download_skin(self, img_name): “““下载皮肤图片””” img_url = parse.urljoin(self.skin_url, self.skin_detail_url) request = requests.get(img_url) if request.status_code == 200: print(‘download-%s’ % img_name) img_path = os.path.join(self.img_folder, img_name) with open(img_path, ‘wb’) as img: img.write(request.content) else: print(‘img error!’) def make_folder(self): “““创建图片存储文件夹””” if not os.path.exists(self.img_folder): os.mkdir(self.img_folder) def run(self): “““脚本执行入口””” self.make_folder() hero_list = self.get_hero() for hero in hero_list: hero_no = str(hero[’ename’]) self.detail_url = hero_no + ‘.shtml’ hero_name = hero[‘cname’] self.get_hero_skin(hero_name, hero_no)# 程序执行入口if name == ‘main’: skin = Skin() skin.run()最后其实思路就是这么简单,当然了,如果有其他思路以及想法的,欢迎留言交流。额,差点忘了,大家有兴趣的,可以尝试一下爬取英雄联盟的所有英雄皮肤高清图片,有其他任何问题,也欢迎留言和交流。 ...

November 8, 2018 · 1 min · jiezi