效果展示动图

需求:

博主之前有一段时间突然不想玩微博了,然后正好表弟想玩,就给他用了,手机绑定也换成了他的号码。近期突然又想要玩,就重新开了个号。新号微博空空的,也没有什么关注。于是就产生了两个需求,正好可以借这个机会学习一下自动化测试工具webdriver的基本使用:

1、将原微博的博文搬到新账号

2、用新账号关注原微博的所有关注

涉及:

1、request的基本使用

2、json解析

3、用request下载图片并保存到本地

4、用webdriver登录并发送微博

5、用autoIT解决非input型的文件上传

本篇目录:

1.思路

2.爬取原微博

3.用webdriver启动浏览器登录微博

4.用webdriver发布带图片的微博

5.完整代码

6.效果展示动图

7.参考

图1.封面而已

思路

1、爬取原微博的博文内容,爬一条发一条

2、文字信息保存在list里,图片保存到本地

3、用webdriver实现批量发送微博

4、上传图片借助第三方工具autoIT

注:

为什么用webdriver来发微博而不用微博开放平台的api?

因为发布带图片的微博的api是高级api需要创建应用并通过审核才能申请,而过审并不是可以糊弄的,需要成熟且系统的应用。

爬取原微博

这里会直接引入实战四的代码模块crawl_weibo,其中的getWeibo方法可以获取到指定微博用户的所有微博的json,并提取其中的cards(一个list数组,所有的微博信息都在里边)返回,该模块详细源码参见以上链接末尾。

getWeibo方法:

# 获取指定博主的所有微博card的list

def getWeibo(self,id,page):#id(字符串类型):博主的用户id,page(整型):微博翻页参数

url='https://m.weibo.cn/api/container/getIndex?type=uid&value='+id+'&containerid=107603'+id+'&page='+str(page)

response=requests.get(url)

ob_json=json.loads(response.text)

list_cards=ob_json['cards']

return list_cards# 返回本页所有的cards

首先明确我们要爬取原微博的所有除了转发以外的微博的原文、图片以及来源、点赞数、评论数等其他信息。接下来先分析一下json 的结构,json的格式化推荐json.cn。

图2.json结构

之前教程里也说了,json就是list和dict的互相嵌套,所以只要会用list和dict,搞清楚json结构,提取数据就很容易了。

我们把文字信息提取出来,把图片都下载到本地的一个文件夹里,以便之后发微博上传。对于图片存储,用request来get一下图片的url,获取的返回内容用open创建一个.jpg格式的file来写入。为了上传的时候方便填写图片地址,图片按顺序编号存入项目下的img文件夹中。上传时只需要根据图片总数按序遍历即可

获取微博内容数据代码:

def getContent(self,card):# 获取该card下微博的内容

mblog=card['mblog']

count_img=0# 每条微博重新计数图片数,用于发送图片的地址

text= html.fromstring(mblog['text'])

text=text.xpath('string(.)')#过滤正文中的多余标签

url_img=''

if 'pics' in mblog:#如果mblog中有键'pics',说明该条微博有图片,存储图片到本地

pics=mblog['pics']

for pic in pics:

url_img=pic['large']['url']

ir = requests.get(url_img)

if ir.status_code == 200:# 如果请求已成功

count_img+=1# 给图片计数

open('../img/'+str(count_img)+'.jpg', 'wb').write(ir.content)# 保存在img文件夹下,发送也从这个文件夹下找

scheme=card['scheme']# 原微博链接

created_at=mblog['created_at']# 原微博创建时间

source=mblog['source']# 原微博来源,即终端

reposts_count=mblog['reposts_count']# 原微博转发数

comments_count=mblog['comments_count']# 原微博评论数

attitudes_count=mblog['attitudes_count']# 原微博点赞数

return text,count_img,scheme,created_at,source,reposts_count,comments_count,attitudes_count# 其实返回的是一个list

将getWeibo返回的list(也就是json中的cards)中的一个card传入以上函数,即可返回我们需要的数据,细节见注释。通过这个方法我们需要发布的微博数据已经可以爬取到了,接下来我们要登录微博把它们发布出去。

用webdriver启动浏览器登录微博

webdriver的使用其实非常简单。可以这样描述:

1、用驱动器启动浏览器并打开一个连接

2、根据页面html源码的结构找到指定的元素(按钮、文本框等)

3、对目标元素采取目标动作(点击、输入等)

使用webdriver需要下载selenium模块和浏览器驱动。

1、下载安装selenium模块,命令行:

pip install selenium

2、博主用的是chrome浏览器,所以本篇以其对应的驱动chromedriver.exe为例,百度或者google就可以找到下载链接,下载好了解压到任意路径即可,代码中指定该路径。

3、一定要保证selenium模块、浏览器驱动、浏览器都是最新版本,以免产生不必要的bug。一般pip指令安装的都是最新版本的模块。

做好以上准备之后,就可以在代码里引入webdriver了,我们先用登录来打个样儿。代码要做的就是驱动启动浏览器后,get微博的主页,用driver的各种find_element方法找到账号和密码输入框,键入账号密码进行登录,有时可能需要验证。以下展示的是账号输入框的位置与属性:

图3.账号输入框位置

webdriver的基本使用:

1、可以根据class和id来找到元素,也可以用xpath语法和css选择器来找到元素

driver.find_element_by_id('id')

driver.find_element_by_class_name('classname')

driver.find_element_by_css_selector('input[type="password"]')

driver.find_element_by_xpath('//div[@node-type="textElDiv"]/textarea[@class="W_input"]')

2、用element.click点击元素,用element.send_keys向文本框键入文字,其他动作可以用ActionChains,参考selenium之 玩转鼠标键盘操作(ActionChains)。

3、详细说明可参考Python爬虫利器五之Selenium的用法,更多用法参考网络教程和文档。

登录代码:

driver = webdriver.Chrome(executable_path='../drivers/chromedriver.exe')# chrome浏览器驱动

url='http://weibo.com/'

driver.get(url)# get打开微博主页

input_account=driver.find_element_by_id('loginname')# 找到账号输入框

input_psw=driver.find_element_by_css_selector('input[type="password"]')# 找到密码输入框

#输入账号密码并登录

input_account.send_keys('account')

input_psw.send_keys('password')

bt_logoin=driver.find_element_by_class_name('login_btn')# 找到登录按钮

bt_logoin.click()# 点击登录

不过以上代码在网络状态不好的时候会产生找不到元素的bug,这主要是因为页面还没有加载完毕造成的。

应该将find账号输入框的代码修改为:

# 参数10为超时时间,即最大等待时间为10秒,关于lambda就自行百度吧

bt_logoin=WebDriverWait(driver,10).until(lambda x:x.find_element_by_id('loginname'))

出现验证码的情况:

在点击了登录按钮以后,有时会出现验证码。对于这种情况,我们只需要加入一个判断,如果点击登录后出现了验证码输入框,就断定需要输入验证码,我们在控制台手动输入并send_keys到验证码输入框即可。(验证码自动破解比较复杂,不建议在入门阶段研究)

处理验证码的代码:

# 根据验证框的存在与否判断是否要输入验证码

def isVerifyCodeExist(self):

try:# 如果成功找到验证码输入框返回true

self.driver.find_element_by_css_selector('input[name="verifycode"]')

return True

except:# 如果异常返回false

return False

# 输入验证码部分,如果无需输入则直接返回,否则手动输入成功后返回

def inputVerifyCode(self):

input_verifycode=self.driver.find_element_by_css_selector('input[name="verifycode"]')# 验证码输入框

bt_change=self.driver.find_element_by_css_selector('img[action-type="btn_change_verifycode"]')# 验证码图片,点击切换

bt_logoin=self.driver.find_element_by_class_name('login_btn')# 登录按钮

while self.isVerifyCodeExist():# 如果验证码输入框一直存在,则一直循环

print u'请输入验证码……(输入"c"切换验证码图片)'

verifycode=raw_input()

if verifycode=='c':

bt_change.click()

else:

input_verifycode.send_keys(verifycode)

bt_logoin.click()

# 点击完登录以后判断是否成功

if self.driver.current_url.split('/')[-1]=='home':# 如果连接已经跳转到home

print u'登录成功'

break

else:

print u'输入的验证码不正确'

在之前的登录代码末尾调用inputVerifyCode方法即可。

用webdriver发布带图片的微博

如果仅发布文字内容的微博,比较简单,思路与以上同理,先找到文本框元素,用send_keys输入内容,找到'发布'按钮,点击按钮即可发布。

# 上传文字

def upload_txt(self,text):

# 用xpath语法找到输入框

input_w=self.driver.find_element_by_xpath('//div[@node-type="textElDiv"]/textarea[@class="W_input"]')

input_w.send_keys(text)

# 发布

def send(self):

# 找到发布按钮并点击

self.driver.find_element_by_class_name('W_btn_a').click()

而对于需要发布图片的博文,我们还需要点击图片->点击单图/多图。接着我们可以发现目标对象不是input型的文件上传按钮,input型的文件上传我们可以用send_keys直接键入文件地址,方便快捷。但是微博这个文件上传是object型的,这只能借助第三方工具autoIT来对os弹窗进行一波骚操作了。

图4.图片上传按钮

从上图看,可以发现这个object的id包括'swf_upbtn'这样一个字段,之后很明显是一个随时可能变化的数字串,所以我们可以用xpath的contains函数来找到它,点击这个按钮以后会弹出上传文件的窗口,这个窗口就不是selenium能控制的了,需要编写autoIT脚本来控制文件的上传操作,再在python代码中通过os模块调用这个脚本。

我的autoIT脚本代码:

WinWait("打开","",10000);

ControlFocus("打开", "", "Edit1");

ControlSetText("打开" ,"", "Edit1", $CmdLine[1]);

Sleep(1000)

ControlClick("打开", "","Button1");

上述代码进行的操作是:

1、等待文件上传窗口的出现,最多等待10s(因为chrome浏览器的文件上传窗口标题是"打开",第一个参数是窗口标题)

2、将光标聚焦于文件地址编辑框

3、在编辑框里键入参数(也就是我们之后会传入的地址)

4、点击"打开"按钮

详细用法和说明请参阅以上两篇。

$CmdLine[1]可以读取到命令行的第一个参数,通过这个参数我们就可以把文件地址传入。关于参数的说明和其他的实现文件上传的方法参考Python Selenium —— 文件上传、下载,其实很简单。

上传文字和图片的方法封装如下:

# 上传文字

def upload_txt(self,text):

input_w=self.driver.find_element_by_xpath('//div[@node-type="textElDiv"]/textarea[@class="W_input"]')

input_w.send_keys(text)

sleep(1)

#运行上传图片脚步

def upload_img_script(self,time_bef,time_after,path):# path参数需要前后带双引号

sleep(time_bef)# 等待弹窗时间

os.system('C:/Users/15850/Documents/GitHub/MyWorkspace/py_study/script/upload.exe '+path)

sleep(time_after)# 等待图片加载时间

# 上传文字和单图

def upload_txt_img(self,text,img_path):

self.upload_txt(text)# 将文字上传

img=self.driver.find_element_by_css_selector('a[action-type="multiimage"]')# 图片按钮

img.click()# 点击图片按钮

sleep(1)# 等待加载其他按钮

#单图/多图按钮,即上传图片按钮

bt_uploadimg=WebDriverWait(self.driver,10).until(lambda x:x.find_element_by_xpath('//object[contains(@id,"swf_upbtn")]'))

bt_uploadimg.click()# 点击上传按钮

self.upload_img_script(1,2,img_path)

# 上传文字和多图

def upload_txt_multiImg(self,text,img_path_list):

self.upload_txt_img(text,img_path_list[0])# 将文字和第一张图片上传

len_imgs=len(img_path_list)# 图片地址list的长度

bt_uploadimg=WebDriverWait(self.driver,10).until(lambda x:x.find_element_by_xpath('//li[@node-type="uploadBtn"]/div/object[contains(@id,"swf_upbtn")]'))

for i in range(len_imgs-1):# 将剩余图片上传

bt_uploadimg.click()

self.upload_img_script(1, 2,img_path_list[i+1])

其中这一行即是调用了编译成exe文件的上传文件的脚步,参数字符串先指明脚本路径,空一格加上path这个参数。

os.system('C:/Users/15850/Documents/GitHub/MyWorkspace/py_study/script/upload.exe '+path)

注意path传入的字符串必须带双引号,字符串本身也需要单引号包括,且分隔符必须为"\",如下:

'"C:\\Users\\15850\\Documents\\GitHub\\MyWorkspace\\py_study\\img\\1.jpg"'

完整代码

(源码已上传github:python爬虫入门实战)

1、主要操作步骤写在weibo_transport模块中

2、引入crawl_weibo模块用于爬取原微博数据

3、引入upload_driver模块用于将数据发布到新账号上

4、3个模块分别位于github项目中的crawl与weibo文件夹下

weibo_transport模块

# -*- coding:utf-8 -*-

'''

Created on 2017年6月25日

@author: wycheng

'''

from crawl import crawl_weibo

import upload_driver

from lxml import html

import requests

def getContent(card):# 获取该card下微博的内容

mblog=card['mblog']

count_img=0# 每条微博重新计数图片数,用于发送图片的地址

text= html.fromstring(mblog['text'])

text=text.xpath('string(.)')#过滤正文中的多余标签

url_img=''

if 'pics' in mblog:#有图片的存储图片

pics=mblog['pics']

for pic in pics:

url_img=pic['large']['url']

ir = requests.get(url_img)

if ir.status_code == 200:# 如果请求已成功

count_img+=1# 给图片计数

open('../img/'+str(count_img)+'.jpg', 'wb').write(ir.content)# 保存在img文件夹下,发送也从这个文件夹下找

print u'图片:'+url_img

scheme=card['scheme']

created_at=mblog['created_at']

source=mblog['source']

reposts_count=mblog['reposts_count']

comments_count=mblog['comments_count']

attitudes_count=mblog['attitudes_count']

return text,count_img,scheme,created_at,source,reposts_count,comments_count,attitudes_count# 其实返回的是一个list

#登录

uploader=upload_driver.Uploader()

uploader.login('account', 'password')# 填写你的账号密码

crawl_weibo=crawl_weibo.CrawlWeibo()

# 先爬取第34页进行发布,作为范例

# 这里的页码不是微博客户端上的页码,这个接口返回的一页只有10个card

# 博主原微博有370+条微博,所以一共有38页

cards=crawl_weibo.getWeibo('2622535523',34)# 第一个参数是用户id,第二个是页数

len_cards=len(cards)

for j in range(len_cards):

index=len_cards-1-j

card=cards[index]

# (微博的cardtype==9,实战四也有说明,转发的微博mblog里有‘retweeted_status’这个key)

if card['card_type']==9 and not 'retweeted_status' in card['mblog']:# 如果这是一条非转发的微博的card

# 获取这条微博的各个数据

content_list=getContent(card)

text,count_img,scheme,created_at,source,reposts_count,comments_count,attitudes_count=content_list

# 发送这条微博的内容到新账号

# 拼接要发送的文本

text=created_at+u' 来自 '+source+'\n'+text+' \n'+u'转发 '+str(reposts_count)+u' 评论 '+str(comments_count)+u' 点赞 '+str(attitudes_count)

path_list=[]# 图片地址list

for i in range(count_img):# 根据图片总数量生成所有图片地址

path_list.append('C:\\Users\\15850\\Documents\\GitHub\\MyWorkspace\\py_study\\img\\'+str(i+1)+'.jpg')

# 上传内容

if count_img==0:# 没有图片

uploader.upload_txt(text)

elif count_img==1:# 单张图片

uploader.upload_txt_img(text, path_list[0])

else:# 多张图片

uploader.upload_txt_multiImg(text,path_list)

uploader.send()

upload_driver模块

# -*- coding:utf-8 -*-

'''

Created on 2017年6月25日

@author: wycheng

'''

from selenium import webdriver

from selenium.webdriver.support.ui import WebDriverWait

from time import sleep

import os

class Uploader:

driver = webdriver.Chrome(executable_path='../drivers/chromedriver.exe')# chrome浏览器驱动

# 根据验证框的存在与否判断是否要输入验证码

def isVerifyCodeExist(self):

try:# 如果成功找到验证码输入框返回true

self.driver.find_element_by_css_selector('input[name="verifycode"]')

return True

except:# 如果异常返回false

return False

# 输入验证码部分,如果无需输入则直接返回,否则手动输入成功后返回

def inputVerifyCode(self):

input_verifycode=self.driver.find_element_by_css_selector('input[name="verifycode"]')# 验证码输入框

bt_change=self.driver.find_element_by_css_selector('img[action-type="btn_change_verifycode"]')# 验证码图片,点击切换

bt_logoin=self.driver.find_element_by_class_name('login_btn')# 登录按钮

while self.isVerifyCodeExist():

print u'请输入验证码……(输入"c"切换验证码图片)'

verifycode=raw_input()

if verifycode=='c':

bt_change.click()

else:

input_verifycode.send_keys(verifycode)

bt_logoin.click()

# 点击完登录以后判断是否成功

if self.driver.current_url.split('/')[-1]=='home':

print u'登录成功'

break

else:

print u'输入的验证码不正确'

#打开微博首页进行登录的过程

def login(self,account,password):

self.driver.implicitly_wait(10)# 设置隐性等待时间,等待页面加载完成才会进行下一步,最多等待10秒

url='http://weibo.com/'

self.driver.get(url)

#输入账号密码并登录

WebDriverWait(self.driver,10).until(lambda x:x.find_element_by_id('loginname')).send_keys(account)

self.driver.find_element_by_css_selector('input[type="password"]').send_keys(password)

bt_logoin=self.driver.find_element_by_class_name('login_btn')

bt_logoin.click()

#如果存在验证码,则进入手动输入验证码过程

if self.isVerifyCodeExist():

self.inputVerifyCode()

# 上传文字

def upload_txt(self,text):

input_w=self.driver.find_element_by_xpath('//div[@node-type="textElDiv"]/textarea[@class="W_input"]')

input_w.send_keys(text)

sleep(1)

#运行上传图片脚步

def upload_img_script(self,time_bef,time_after,path):# path参数需要前后带双引号

sleep(time_bef)# 等待弹窗时间

os.system('C:/Users/15850/Documents/GitHub/MyWorkspace/py_study/script/upload.exe '+path)

sleep(time_after)# 等待图片加载时间

# 上传文字和单图

def upload_txt_img(self,text,img_path):

self.upload_txt(text)# 将文字上传

img=self.driver.find_element_by_css_selector('a[action-type="multiimage"]')# 图片按钮

img.click()# 点击图片按钮

sleep(1)# 等待加载其他按钮

#单图/多图按钮,即上传图片按钮

bt_uploadimg=WebDriverWait(self.driver,10).until(lambda x:x.find_element_by_xpath('//object[contains(@id,"swf_upbtn")]'))

bt_uploadimg.click()# 点击上传按钮

self.upload_img_script(1,2,img_path)

# 上传文字和多图

def upload_txt_multiImg(self,text,img_path_list):

self.upload_txt_img(text,img_path_list[0])# 将文字和第一张图片上传

len_imgs=len(img_path_list)# 图片地址list的长度

bt_uploadimg=WebDriverWait(self.driver,10).until(lambda x:x.find_element_by_xpath('//li[@node-type="uploadBtn"]/div/object[contains(@id,"swf_upbtn")]'))

for i in range(len_imgs-1):# 将剩余图片上传

bt_uploadimg.click()

self.upload_img_script(1, 2,img_path_list[i+1])

# 发布

def send(self):

self.driver.find_element_by_class_name('W_btn_a').click()

sleep(4)# 等待发送成功字样消失

效果展示动图

效果展示动图

参考

python爬网络图片脚步_python爬虫入门 实战(五)---用webdriver实现批量自动发微博...相关推荐

  1. python编程理论篇_Python爬虫入门实战之猫眼电影数据抓取(理论篇)

    前言 本文可能篇幅较长,但是绝对干货满满,提供了大量的学习资源和途径.达到让读者独立自主的编写基础网络爬虫的目标,这也是本文的主旨,输出有价值能够真正帮助到读者的知识,即授人以鱼不如授人以渔,让我们直 ...

  2. python爬取方式_Python 爬虫入门(三)—— 寻找合适的爬取策略

    写爬虫之前,首先要明确爬取的数据.然后,思考从哪些地方可以获取这些数据.下面以一个实际案例来说明,怎么寻找一个好的爬虫策略.(代码仅供学习交流,切勿用作商业或其他有害行为) 1).方式一:直接爬取网站 ...

  3. python爬虫入门实战---------一周天气预报爬取_Python爬虫入门实战--------一周天气预报爬取【转载】【没有分析...

    Python爬虫入门实战--------一周天气预报爬取[转载][没有分析 Python爬虫入门实战--------一周天气预报爬取[转载][没有分析] 来源:https://blog.csdn.ne ...

  4. python爬虫动态加载_python爬虫入门实战(四)!爬取动态加载的页面!

    今天的主题是爬取动态网页的经验分享,以cocos论坛为例子进行分享.(官方不会打我吧 ) 配置环境 为什么选择cocos论坛呢?因为自己在浏览论坛时,发现标题内容会随着滚动条的位置而动态添加. 环境: ...

  5. python xpath入门_python爬虫入门实战(三)!xpath 和 csv!

    最近有小伙伴说正则表达式学不懂?那有什么替代方案呢?一起往下看吧! 在前两篇文章我们已经学了一些基本技巧.但是之前都是用正则表达式来解析内容的,可能有小伙伴对正则表达式不理解,于是乎,我找到一个相对好 ...

  6. layui 如何动态加载局部页面_python爬虫入门实战(四)!爬取动态加载的页面!

    今天的主题是爬取动态网页的经验分享,以cocos论坛为例子进行分享.(官方不会打我吧 ) 配置环境 为什么选择cocos论坛呢?因为自己在浏览论坛时,发现标题内容会随着滚动条的位置而动态添加. 环境: ...

  7. python爬虫-爬妹子图_Python 爬虫入门之爬取妹子图

    Python 爬虫入门之爬取妹子图 来源:李英杰  链接: https://segmentfault.com/a/1190000015798452 听说你写代码没动力?本文就给你动力,爬取妹子图.如果 ...

  8. python爬取喜马拉雅_Python爬虫实战案例之爬取喜马拉雅音频数据详解

    这篇文章我们来讲一下在网站建设中,Python爬虫实战案例之爬取喜马拉雅音频数据详解.本文对大家进行网站开发设计工作或者学习都有一定帮助,下面让我们进入正文. 前言 喜马拉雅是专业的音频分享平台,汇集 ...

  9. python 爬网站 实例_python爬虫实战:之爬取京东商城实例教程!(含源代码)

    前言: 本文主要介绍的是利用python爬取京东商城的方法,文中介绍的非常详细,下面话不多说了,来看看详细的介绍吧. 主要工具 scrapy BeautifulSoup requests 分析步骤 1 ...

  10. python爬京东联盟_python爬虫框架scrapy实战之爬取京东商城进阶篇

    前言 之前的一篇文章已经讲过怎样获取链接,怎样获得参数了,详情请看python爬取京东商城普通篇,本文将详细介绍利用python爬虫框架scrapy如何爬取京东商城,下面话不多说了,来看看详细的介绍吧 ...

最新文章

  1. 云计算(2)it 是什么
  2. 尝试引用已删除的函数_学Excel函数公式,你必须要掌握这些知识
  3. 微信自动关闭内置浏览器页面,返回公众号窗口 WeixinJSBridge.call('closeWindow')
  4. vue企业项目demo_基于SpringBoot和Vue的企业级中后台开源项目
  5. java7 xp版下载64位_JRE7 64位下载|JRE7 64位(java运行环境) V1.7.0.65官方版
  6. APR 以及linux安装apr 库目的
  7. log4net直切ElasticSearch,小步快跑首选
  8. Android逆向笔记-通过字符串定位跳转点
  9. 变量在函数内外的作用域 3
  10. [Web Chart系列之三] 图形布局-Layout
  11. 文件复制 详解(C++)
  12. 时间管理-要抽专门的时间去做那些重要但不紧急的事情
  13. java查找PDF关键字坐标 并且标记出来
  14. 写给小白的区块链科普文
  15. [虚幻引擎] UE4/5数字孪生 制作城市光束效果
  16. vim 打开文件乱码
  17. php和mysql不在一台机器上_MySQL_在同一台机器上运行多个 MySQL 服务,**************************************** - phpStudy...
  18. cholesky 分解加速求解线性方程组
  19. 【消息中心】架构准备
  20. EPUB阅读器聚合-Android

热门文章

  1. 一天天学WG--第一天
  2. matlab postion gcf
  3. 编程中,有哪些好的习惯一开始就值得坚持?
  4. 台式计算机设置热点,台式电脑怎样设置wifi热点?设置wifi热点流程一览
  5. kerberos认证下kafka报错Bootstrap broker host:ip (id: -1 rack: null) disconnected
  6. html背景颜色渐变色代码,css3背景渐变色代码
  7. Sizes of tensors must match except in dimension 1. Got 85 and 6 in dimension 2
  8. 判断闰年简单逻辑运算符
  9. 热搜大事记【2018-11-05-2018-11-11】
  10. Pycharm 编辑器取消中间分割线