python爬虫入门 之 单线程 + 多任务异步协程
5.1 进程和线程
-
自己写一个服务端
from flask import Flask
import time
app = Flask(__name__)
-
同步代码
from multiprocessing.dummy import Pool
import requests
import time
start = time.time()
pool = Pool(3)
urls = ["http://127.0.0.1:5000/one","http://127.0.0.1:5000/two","http://127.0.0.1:5000/three"]
for url in urls:
page_text = requests.get(url,).text
print(page_text)
print('总耗时:',time.time()-start) -
异步代码
from multiprocessing.dummy import Pool
import requests
import time
start = time.time()
pool = Pool(3)
urls = ["http://127.0.0.1:5000/one","http://127.0.0.1:5000/two","http://127.0.0.1:5000/three"]
def get_request(url):
return requests.get(url).text
response_list = pool.map(get_request,urls)
print(response_list)
#解析
def parse(page_text):
print(len(page_text))
pool.map(parse,response_list)
print('总耗时:',time.time()-start)
print('总耗时:',time.time()-start)
5.2 协程
-
asyncio链接https://www.liaoxuefeng.com/wiki/1016959663602400/1017970488768640
-
是一个对象,可以将协程当做一个特殊的函数,如果一个函数的定义被 anync 关键字所修饰,该特殊函数被调用后,函数内部的程序语句不会立即执行 ,而是返回一个协程对象
from time import sleep
async def get_request(url):
print('正在请求:',url)
sleep(2)
print('请求结束')
c = get_request("www.baidu.com")
print(c) # <coroutine object get_request at 0x000000000A184308>
5.3任务对象(task)
-
所谓的任务对象就是对携程对象的进一步封装,在任务对象中可以实现显示协程对象的运行状况,
-
特点
-
任务对象最终是要被注册到事件循环对象中的.
-
回调函数是绑定给任务对象的,只有当任务对象对应的特殊函数被执行完毕后,回调函数才会被执行
-
-
await 挂起的操作,可理解为交出cpu的使用权
-
事件循环对象
-
无限循环的对象,也可以把其当成是某一种容器,该容器中需要放入多个任务对象(就是一组待执行的代码块)
-
异步的体现 :当事件循环开始后,该对象会按照顺序执行每一个任务对象,当一个任务对象发生阻塞时不会等待,而是直接执行下一个任务对象
from time import sleep
import asyncio
#回调函数
def callback(task):
print("i am callback")
print(task.result()) #result 返回的就是任务对象对应的哪个特殊函数的返回值
async def get_request(url):
print('正在请求:',url)
sleep(2)
print('请求结束')
return "hello world"
#创建一个携程对象
c = get_request("www.baidu.com")
#封装一个任务对象
task = asyncio.ensure_future(c)
#给任务对象绑定回调函数
task.add_done_callback(callback)
#创建一个事件循环对象
loop = asyncio.get_event_loop()
#将任务对象注册到事件循环中并且开启了事件循环
loop.run_until_complete(task) -
5.4多任务异步协程
#注意事项:
1.将多个任务对象存储到一个列表中,然后将该列表注册到事件循环中,在注册的过程中,该列表需要被wait方法进行处理
2.在任务对象对应的特殊函数内部的实现中,不可以出现不支持异步模块的代码,否则就会中断整个的异步效果,并且在该函数的每一阻塞的操作都必须使用await关键字进行修饰
3.requests模块对应的代码不可以出现在特殊函数内部,因为requests 不支持异步操作
import time
import asyncio
start = time.time()
urls = [
"http://127.0.0.1:5000/one",
"http://127.0.0.1:5000/one",
"http://127.0.0.1:5000/two",
"http://127.0.0.1:5000/three"
]
#待执行的代码块中不可以出现不支持异步模块的代码
#在该函数内部如果有阻塞,阻塞操作必须使用await关键字修饰
async def get_request(url):
print('正在请求:',url)
# await不用不会报错,但不会有异步效果
await asyncio.sleep(2)
print('请求结束')
return "hello world"
#放置所有的任务对象
tasks = []
for url in urls:
c = get_request(url)
task = asyncio.ensure_future(c)
tasks.append(task)
loop = asyncio.get_event_loop()
#wait不用会报错
loop.run_until_complete(asyncio.wait(tasks))
print("所用时长:",time.time()-start)
5.4.1在爬虫中使用 多任务异步协程
import time
import asyncio
import requests
start = time.time()
urls = [
"http://127.0.0.1:5000/one",
"http://127.0.0.1:5000/two",
"http://127.0.0.1:5000/three"
]
# 无法实现异步的效果,因为requests 不支持异步操作
async def req(url):
page_text = await requests.get(url).text
return page_text
#构建任务列表
tasks = []
for url in urls:
#协程对象
c = req(url)
#任务对象
task = asyncio.ensure_future(c)
tasks.append(task)
#创建事件循环对象
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
print(time.time()-start)
如上图,我们会发现出现了一个错误,我们尝试了解决,发现:
#无法实现异步的效果,因为requests 不支持异步操作
所以我们引用了了aiohttp模块
5.4.2 aiohttp模块
-
一个支持异步操作的网络请求的模块
-
环境的安装 pip install aiohttp
-
记忆步骤:
第一步: 初步架构
async def req(url):
with aiohttp.ClientSession() as s:
with s.get(url) as response:
page_text = response.text()
return page_text第二步: 补充细节
在每一个 with 之前加上 async,在每一步阻塞前加上 await
async def req(url):
async with aiohttp.ClientSession() as s:
async with await s.get(url) as response:
page_text = await response.text()
return page_textserver端代码
from flask import Flask, render_template
import time
app = Flask(__name__)
客户端代码
import time
import asyncio
import aiohttp
from lxml import etree
start = time.time()
urls = [
"http://127.0.0.1:5000/one",
"http://127.0.0.1:5000/two",
"http://127.0.0.1:5000/three"
]
# 无法实现异步的效果,因为requests 不支持异步操作
async def req(url):
async with aiohttp.ClientSession() as s:
async with await s.get(url) as response:
# response.read() 返回 byte 类型的数据
# response.text() 返回 字符串
page_text = await response.text()
return page_text
# 细节的补充 : 在每一个 with 之前加上 async,在每一步阻塞前加上 await
def parse(task):
page_text = task.result()
tree = etree.HTML(page_text)
name = tree.xpath("//p/text()")[0]
print(name)
#构建任务列表
tasks = []
for url in urls:
#协程对象
c = req(url)
#任务对象
task = asyncio.ensure_future(c)
task.add_done_callback(parse)
tasks.append(task)
#创建事件循环对象
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
print(time.time()-start)
第六章 .图片懒加载技术、selenium和PhantomJS
6.1图片懒加载
-
案例分析:抓取站长素材http://sc.chinaz.com/中的图片数据
import requests
from lxml import etree
if __name__ == "__main__":
url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html'
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}
#获取页面文本数据
response = requests.get(url=url,headers=headers)
response.encoding = 'utf-8'
page_text = response.text
#解析页面数据(获取页面中的图片链接)
#创建etree对象
tree = etree.HTML(page_text)
div_list = tree.xpath('//div[@id="container"]/div')
#解析获取图片地址和图片的名称
for div in div_list:
image_url = div.xpath('.//img/@src')
image_name = div.xpath('.//img/@alt')
print(image_url) #打印图片链接
print(image_name)#打印图片名称 -
运行结果观察发现,我们可以获取图片的名称,但是链接获取的为空,检查后发现xpath表达式也没有问题,究其原因出在了哪里呢?
-
图片懒加载概念:
-
图片懒加载是一种网页优化技术。图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间。为了解决这种问题,通过前后端配合,使图片仅在浏览器当前视窗内出现时才加载该图片,达到减少首屏图片请求数的技术就被称为“图片懒加载”。
-
-
-
网站一般如何实现图片懒加载技术呢?
-
在网页源码中,在img标签中首先会使用一个“伪属性”(通常使用src2,original......)去存放真正的图片链接而并非是直接存放在src属性中。当图片出现到页面的可视化区域中,会动态将伪属性替换成src属性,完成图片的加载。
-
-
站长素材案例后续分析:通过细致观察页面的结构后发现,网页中图片的链接是存储在了src2这个伪属性中
import requests
from lxml import etree
if __name__ == "__main__":
url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html'
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}
#获取页面文本数据
response = requests.get(url=url,headers=headers)
response.encoding = 'utf-8'
page_text = response.text
#解析页面数据(获取页面中的图片链接)
#创建etree对象
tree = etree.HTML(page_text)
div_list = tree.xpath('//div[@id="container"]/div')
#解析获取图片地址和图片的名称
for div in div_list:
image_url = div.xpath('.//img/@src2') #src2伪属性
image_name = div.xpath('.//img/@alt')
print(image_url) #打印图片链接
print(image_name)#打印图片名称
6.2 selenium
-
概念: selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器
-
环境的安装 : pip install selenium
-
selenium的演示程序
from selenium import webdriver
from time import sleep
# 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的
driver = webdriver.Chrome(r'E:\after homework\day105\chromedriver.exe')
# 用get打开百度页面
driver.get("http://www.baidu.com")
# 查找页面的“设置”选项,并进行点击
driver.find_elements_by_link_text('设置')[0].click()
sleep(2)
# # 打开设置后找到“搜索设置”选项,设置为每页显示50条
driver.find_elements_by_link_text('搜索设置')[0].click()
sleep(2)
# 选中每页显示50条
m = driver.find_element_by_id('nr')
sleep(2)
m.find_element_by_xpath('//*[@id="nr"]/option[3]').click()
m.find_element_by_xpath('.//option[3]').click()
sleep(2)
# 点击保存设置
driver.find_elements_by_class_name("prefpanelgo")[0].click()
sleep(2)
# 处理弹出的警告页面 确定accept() 和 取消dismiss()
driver.switch_to_alert().accept()
sleep(2)
# 找到百度的输入框,并输入 美女
driver.find_element_by_id('kw').send_keys('美女')
sleep(2)
# 点击搜索按钮
driver.find_element_by_id('su').click()
sleep(2)
# 在打开的页面中找到“Selenium - 开源中国社区”,并打开这个页面
driver.find_elements_by_link_text('美女_百度图片')[0].click()
sleep(3)
# 关闭浏览器
driver.quit() -
selenium和爬虫之间的关联?
1.便捷的获取页面中动态加载的数据
requests模块进行数据爬取,所见非所得
selenium所见即可得,但速度较慢
2.实现模拟登陆 -
基本操作
-
谷歌浏览器驱动程序下载地址: http://chromedriver.storage.googleapis.com/index.html
-
驱动程序和谷歌版本的映射关系表:https://blog.csdn.net/huilan_same/article/details/51896672
#步骤:
1.实例化某一款浏览器对象(驱动程序的路径)
2.find系列的函数用于标签定位
-
-
浏览器创建
-
Selenium支持非常多的浏览器,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面浏览器PhantomJS。
from selenium import webdriver
browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.PhantomJS()
browser = webdriver.Safari()
-
-
元素定位
-
webdriver 提供了一系列的元素定位方法,常用的有以下几种:
find_element_by_id()
find_element_by_name()
find_element_by_class_name()
find_element_by_tag_name()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_xpath()
find_element_by_css_selector() -
-
节点交互
-
Selenium可以驱动浏览器来执行一些操作,也就是说可以让浏览器模拟执行一些动作。比较常见的用法有:输入文字时用
send_keys()
方法,清空文字时用clear()
方法,点击按钮时用click()
方法。示例如下:from selenium import webdriver
import time
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input = browser.find_element_by_id('q')
input.send_keys('MAC')
time.sleep(1)
input.clear()
input.send_keys('IPhone')
button = browser.find_element_by_class_name('btn-search')
button.click()
browser.quit()
-
-
爬取单页数据
from selenium import webdriver
from time import sleep
#实例化一个浏览器对象
bro = webdriver.Chrome(executable_path=r'E:\after homework\day105\chromedriver.exe') #executable_path 当前浏览器的驱动程序
url = "https://www.jd.com/"
#get 用于发起请求
bro.get(url)
#定位指定标签
search_input = bro.find_element_by_id("key")
#对指定标签进行数据交互
search_input.send_keys("macPro")
btn = bro.find_element_by_xpath('//*[@id="search"]/div/div[2]/button')
btn.click()
sleep(2)
#执行js代码
jsCode = 'window.scrollTo(0,document.body.scrollHeight)'
bro.execute_script(jsCode)
sleep(3)
bro.quit() -
爬取多页数据
from selenium import webdriver
from time import sleep
from lxml import etree
page_text_list = []
#实例化一个浏览器对象
bro = webdriver.Chrome(executable_path=r'E:\after homework\day105\chromedriver.exe') #executable_path 当前浏览器的驱动程序
url = "http://125.35.6.84:81/xk/"
#get 用于发起请求
bro.get(url)
sleep(2)
#page_source就是当前浏览器打开页面对应的源码数据
page_text = bro.page_source
page_text_list.append(page_text)
for i in range(2):
bro.find_element_by_id('pageIto_next').click()
sleep(2)
page_text = bro.page_source
page_text_list.append(page_text)
for page_text in page_text_list:
tree = etree.HTML(page_text)
li_list = tree.xpath('//*[@id="gzlist"]/li')
for li in li_list:
name = li.xpath('./dl/@title')[0]
print(name)
sleep(4)
bro.quit() -
动作链 :一系列的行为动作
地址 https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable
from selenium import webdriver
from selenium.webdriver import ActionChains #动作链
from time import sleep
page_text_list = []
#实例化一个浏览器对象,executable_path 当前浏览器的驱动程序
bro = webdriver.Chrome(executable_path=r'E:\after homework\day105\chromedriver.exe')
url = "https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable"
bro.get(url)
# 如果定位的标签是存在于 iframe 对应的子页面中,在定位标签前一定要进行 switch_to 的操作
bro.switch_to.frame('iframeResult') # iframe标签的id
div_tag = bro.find_element_by_id("draggable")
# 错误 :selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element:
#实例化动作链对象
action = ActionChains(bro)
#点击且长按
action.click_and_hold(div_tag)
#模拟人移动算法(自己百度)
#这里提供一个简单操作
for i in range(5):
# perform :让动作链立即执行
action.move_by_offset(17,0).perform()
sleep(0.5)
#释放动作链
action.release()
sleep(3)
bro.quit() -
执行JavaScript
-
对于某些操作,Selenium API并没有提供。比如,下拉进度条,它可以直接模拟运行JavaScript,此时使用
execute_script()
方法即可实现,代码如下:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.jd.com/')
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("123")') -
-
获取页面源码数据
-
通过
page_source
属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了
-
-
前进和后退
-
模拟浏览器的前进后退
import time
from selenium import webdriver
browser=webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.get('https://www.taobao.com')
browser.get('http://www.sina.com.cn/')
browser.back()
time.sleep(10)
browser.forward()
browser.close() -
-
Cookie处理
-
使用Selenium,还可以方便地对Cookies进行操作,例如获取、添加、删除Cookies等。示例如下:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())
-
-
异常处理
from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameException
try:
browser=webdriver.Chrome()
browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
browser.switch_to.frame('iframssseResult')
except TimeoutException as e:
print(e)
except NoSuchFrameException as e:
print(e)
finally:
browser.close()
6.3 phantomJS
-
PhantomJS是一款无界面的浏览器,其自动化操作流程和上述操作谷歌浏览器是一致的。由于是无界面的,为了能够展示自动化操作流程,PhantomJS为用户提供了一个截屏的功能,使用save_screenshot函数实现。
-
无头浏览器 :无可视化界面的浏览器
-
phantomJS
谷歌无头浏览器
from selenium import webdriver
from time import sleep
from selenium.webdriver.chrome.options import Options
# 创建一个参数对象,用来控制chrome以无界面模式打开
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
page_text_list = []
#实例化一个浏览器对象,executable_path 当前浏览器的驱动程序
bro = webdriver.Chrome(executable_path=r'E:\after homework\day105\chromedriver.exe',chrome_options=chrome_options)
bro.get('https://www.baidu.com')
sleep(2)
#截图
bro.save_screenshot("1.png")
print(bro.page_source)
sleep(2)
bro.quit() -
-
selenium规避风险
可判断为正常用户的正常请求
执行代码时:
from selenium import webdriver
from selenium.webdriver import ChromeOptions
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
#实例化一个浏览器对象
bro = webdriver.Chrome(executable_path=r'C:\Users\oldboy-python\Desktop\爬虫+数据\day04\chromedriver.exe',options=option)
bro.get('https://www.taobao.com/')
登录qq空间,爬取数据
import requests
from selenium import webdriver
from lxml import etree
import time
driver = webdriver.Chrome(executable_path='/Users/bobo/Desktop/chromedriver')
driver.get('https://qzone.qq.com/')
#在web 应用中经常会遇到frame 嵌套页面的应用,使用WebDriver 每次只能在一个页面上识别元素,对于frame 嵌套内的页面上的元素,直接定位是定位是定位不到的。这个时候就需要通过switch_to_frame()方法将当前定位的主体切换了frame 里。
driver.switch_to.frame('login_frame')
driver.find_element_by_id('switcher_plogin').click()
#driver.find_element_by_id('u').clear()
driver.find_element_by_id('u').send_keys('328410948') #这里填写你的QQ号
#driver.find_element_by_id('p').clear()
driver.find_element_by_id('p').send_keys('xxxxxx') #这里填写你的QQ密码
driver.find_element_by_id('login_button').click()
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
page_text = driver.page_source
tree = etree.HTML(page_text)
#执行解析操作
li_list = tree.xpath('//ul[@id="feed_friend_list"]/li')
for li in li_list:
text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()')
text = ''.join(text_list)
print(text+'\n\n\n')
driver.close()
爬取豆瓣网中的电影信息
from selenium import webdriver
from time import sleep
import time
if __name__ == '__main__':
url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action='
# 发起请求前,可以让url表示的页面动态加载出更多的数据
path = r'C:\Users\Administrator\Desktop\爬虫授课\day05\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe'
# 创建无界面的浏览器对象
bro = webdriver.PhantomJS(path)
# 发起url请求
bro.get(url)
time.sleep(3)
# 截图
bro.save_screenshot('1.png')
# 执行js代码(让滚动条向下偏移n个像素(作用:动态加载了更多的电影信息))
js = 'window.scrollTo(0,document.body.scrollHeight)'
bro.execute_script(js) # 该函数可以执行一组字符串形式的js代码
time.sleep(2)
bro.execute_script(js) # 该函数可以执行一组字符串形式的js代码
time.sleep(2)
bro.save_screenshot('2.png')
time.sleep(2)
# 使用爬虫程序爬去当前url中的内容
html_source = bro.page_source # 该属性可以获取当前浏览器的当前页的源码(html)
with open('./source.html', 'w', encoding='utf-8') as fp:
fp.write(html_source)
bro.quit()
6.4 基于selenium实现12306模拟登陆
链接地址 :https://kyfw.12306.cn/otn/login/init
# ChaoJiYing.py
import requests
from hashlib import md5
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
# 12306模拟登陆
from selenium import webdriver
from selenium.webdriver import ActionChains
#Image用作于图片裁剪
from PIL import Image
from time import sleep
from ChaoJiYing import Chaojiying_Client
#实例化一个浏览器对象,executable_path 当前浏览器的驱动程序
bro = webdriver.Chrome(executable_path=r'E:\after homework\day105\chromedriver.exe')
bro.get("https://kyfw.12306.cn/otn/login/init")
sleep(2)
#验证码图片的捕获
bro.save_screenshot("main.png")
#定位验证码图片对应的标签
code_img_ele = bro.find_element_by_xpath('//*[@id="loginForm"]/div/ul[2]/li[4]/div/div/div[3]/img')
#验证码图片基于当前整张页面左上角坐标
location = code_img_ele.location
#验证码图片的长和宽
size = code_img_ele.size
#裁剪的矩形区域(左下角和右上角两点的坐标)
rangle = (int(location['x']),int(location['y']),int(location['x']+size['width']),int(location['y']+size['height']))
i = Image.open('main.png')
frame = i.crop(rangle)
frame.save('code.png')
#使用打码平台进行验证码的识别
chaojiying = Chaojiying_Client('bobo328410948', 'bobo328410948', '899370') #用户中心>>软件ID 生成一个替换 96001
im = open('code.png', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
result = chaojiying.PostPic(im, 9004)['pic_str']
print(result) # x1,y1|x2,y2|x3,y3 ==> [[x1,y1],[x2,y2],[x3,y3]]
all_list = []#[[x1,y1],[x2,y2],[x3,y3]] 每一个列表元素表示一个点的坐标,坐标对应值的0,0点是验证码图片左下角
if '|' in result:
list_1 = result.split('|')
count_1 = len(list_1)
for i in range(count_1):
xy_list = []
x = int(list_1[i].split(',')[0])
y = int(list_1[i].split(',')[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
else:
x = int(result.split(',')[0])
y = int(result.split(',')[1])
xy_list = []
xy_list.append(x)
xy_list.append(y)
all_list.append(