由于在豆瓣发了个租房帖子, 发现很快就被其他的帖子淹没, 但是手动顶帖实在太累,, 所以想通过自动顶帖的方式来解放双手!
评论请求分析
通过Chrome network 分析
add_comment
评论 url 是
https://www.douban.com/group/topic/129122199/add_comment
需要带 5 个参数, 其中 ck 是 cookie 里面的值, rv_comment 是 评论
返回 302 代表重定向
Python 模拟请求:
- # 豆瓣具体帖子
- url = "https://www.douban.com/group/topic/129122199/"
- # 豆瓣具体帖子回复的接口, 格式是帖子链接 +/add_comment
- comment_url = url + "/add_comment"
- cookie = 'cookie'
- referer = url
- agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) ApplewebKit/537.36 (Khtml, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
- headers = {
- "Host": "www.douban.com",
- "Referer": referer,
- 'User-Agent': agent,
- "Cookie": cookie
- }
- params = {
- "rv_comment": '',
- "ck": re.findall("ck=(.*?);", headers["Cookie"])[-1],
- 'start': '0',
- 'submit_btn': '发送'
- }
- response = requests.post(comment_url, headers=headers, allow_redirects=False,
- data=params, verify=False)
直接运行即可.
但是多运行几次就会发现, 返回的状态码是 200, 而且没有顶帖成功. 实际上是触发了豆瓣的防爬虫.
触发了豆瓣验证码
而且在我们顶帖的时候发送请求的时候还带有 captcha-solution 和 captcha-id 字段.
目前发现, 每次评论就算相隔 1 分钟, 只要满 3 次, 就一定会弹出这个验证码进行验证.
验证码解析
遇到验证码我们就来破解验证码.
tesserocr
识别图形验证码需要安装 tesserocr 这个库, 下面介绍下 tesserocr.
tesserocr 是 Python 的一个 OCR 识别库, 但其实是对 tesseract 做了一层 Python API 的封装, 核心还是 tesseract, 所以在安装 tesserocr 之前, 需要先安装 tesseract.Tesseract(/'tesərækt/) 这个词的意思是" 超立方体 ", 指的是几何学里的四维标准方体, 又称" 正八胞体 ", 是一款被广泛使用的开源 OCR 工具.
在 Mac 下, 使用 brew 安装
brew install tesseract --all-languages
接下来再安装 tesserocr 即可:
- brew install ImageMagick
- pip install tesserocr pillow
Python 代码如下:
- import tesserocr
- from PIL import Image
- if __name__ == '__main__':
- # 新建 Image 对象
- image = Image.open("/Users/liwenhao/Desktop/douban-captcha-example1.jpeg")
- # 调用 tesserocr 的 image_to_text() 方法, 传入 image 对象完成识别
- result = tesserocr.image_to_text(image)
- print(result)
验证的图片如下:
douban-captcha-example1
结果无法识别.
换一张简单的图片试试:
结果如下:
5594
看来 Tesseract 只能识别一些简单的验证码, 不适合豆瓣验证码识别.
试试识别验证码平台.
百度 OCR
官方接入文档: 文字识别 - Python SDK 接入文档
重点: 免费
通用识别 (包括身份证, 银行卡)500 次 / 日,
高精度则 50 次 / 日,
驾驶证, 行驶证, 车票, 营业执照, 通用票据均为 200 次 / 日
注意: 支持 2.7.+ 及 3.+
配置流程:
先开通个百度的账号;
开通文字识别服务, 打开后点击立即使用: https://cloud.baidu.com/product/ocr.html
点击步骤 2, 应该有个信息确认的, 确认后, 会进入到用户个人首页, 向下滑动, 直接点击文字识别:
点击创建应用, 输入一堆内容后, 点击确认即可, 然后点击我的应用, 这里面的 API Key 跟 Secret Key 需要使用到:
点击右上角, 用户中心, 用户 ID 也需要用到:
需要的信息准备好了, pip 安装一波
pip install baidu-aip
测试一波
- import JSON
- from aip import AipOcr
- if __name__ == '__main__':
- APP_ID = ' '
- API_KEY = ' '
- SECRET_KEY = ' '
- client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
- # 读取图片
- def get_file_content(file_path):
- with open(file_path, 'rb') as fp:
- return fp.read()
- image = get_file_content('/Users/liwenhao/Desktop/douban-captcha-example2.jpg')
- """调用通用文字识别 (高精度), 图片参数为本地图片"""
- result = JSON.dumps(client.basicAccurate(image))
- print(result)
验证的图片如下:
douban-captcha-example1
结果走一波:
{"log_id": 3968431492157876638, "words_result_num": 1, "words_result": [{"words": "minute:"}]}
从结果可以看出识别出了这个验证码.
words_result_num 是识别结果数
words_result 是定位和识别结果数组
words 是识别结果字符串
再来试试
douban-captcha-example2
结果如下:
{"log_id": 5251449865676063710, "words_result_num": 0, "words_result": []}
没有识别出来, 可以看到对于复杂一些的验证码还是会出现无法识别的情况, 但是胜在免费.
超级鹰
对于无法识别的情况就需要打码平台了, 业界比较出名的是 超级鹰 http://www.chaojiying.com/ .
超级鹰是按量级收费, 量大便宜, 标准价格: 1 元 = 1000 题分, 不同验证码类型, 需要的题分不一样, 详情可以到这里查询 http://www.chaojiying.com/price.html
python 代码如下:
- from hashlib import md5
- import requests
- import JSON
- # 通过超级鹰识别验证码
- def recognition_captcha(filename, code_type):
- im = open(filename, 'rb').read()
- params = {
- 'user': '账号',
- 'pass2': md5('密码'.encode('utf8')).hexdigest(),
- 'softid': 'softid',
- 'codetype': code_type
- }
- headers = {
- 'Connection': 'Keep-Alive',
- 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
- }
- files = {'userfile': ('ccc.jpg', im)}
- resp = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
- headers=headers).JSON()
- return resp
- # 调用代码
- if __name__ == '__main__':
- print(JSON.dumps(recognition_captcha('/Users/liwenhao/Desktop/douban-captcha-example2.jpg', 1006)))
上传的验证码就是上面百度 OCR 未曾识别的验证码, 如下:
douban-captcha-example2
结果如下:
{"err_str": "OK", "err_no": 0, "md5": "0475b05654c376deb409bfef7eee75cd", "pic_id": "8054415552001300054", "pic_str": "yacvmd"}
发现 验证码 yacvmd 已出来. 但是时间花了 5s 左右. 后来测试发现对于豆瓣比较建的验证码花费的时间在 1s 内, 因此从时间和准确性上面, 最后还是采用了超级鹰打码平台.
失败微信通知
无论采用什么方式, 都有可能出现失败的情况, 我总不能采取 轮询 的方式, 隔几个小时就去看看到底前面几次是否成功, 因此需要一个 异步通知 , 最开始想用 邮件, 后来发现了 Server 酱 http://sc.ftqq.com/3.version 这个神器, 可以帮助我们发送微信通知, 而且特别简单.
具体可以查看 Server 酱 http://sc.ftqq.com/3.version .
完整代码
- import os
- import requests
- import urllib3
- import re
- from hashlib import md5
- import random
- from lxml import HTML
- import logging
- logging.basicConfig(level=logging.INFO, format='%(asctime)s.%(msecs)03d %(levelname)s: %(message)s',
- datefmt='%Y-%m-%d %H:%M:%S')
- urllib3.disable_warnings()
- # 下载验证码图片
- def download_captcha(captcha_url, agent):
- # findall 返回的是一个列表
- captcha_name = re.findall("id=(.*?):", captcha_url)
- filename = "douban_%s.jpg" % (str(captcha_name[0]))
- logging.info("文件名为:" + filename)
- with open(filename, 'wb') as f:
- # 以二进制写入的模式在本地构建新文件
- header = {
- 'User-Agent': agent,
- 'Referer': captcha_url
- }
- f.write(requests.get(captcha_url, headers=header).content)
- logging.info("%s 下载完成" % filename)
- return filename
- # 通过超级鹰识别验证码
- def recognition_captcha(filename, code_type):
- im = open(filename, 'rb').read()
- params = {
- 'user': '用户',
- 'pass2': md5('密码'.encode('utf8')).hexdigest(),
- 'softid': 'softid',
- 'codetype': code_type
- }
- headers = {
- 'Connection': 'Keep-Alive',
- 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
- }
- files = {'userfile': ('ccc.jpg', im)}
- resp = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
- headers=headers).JSON()
- # 错误处理
- if resp.get('err_no', 0) == 0:
- return resp.get('pic_str')
- def result_verification(response):
- if response.status_code == 302:
- logging.info("豆瓣 ding 成功")
- else:
- logging.info(response.status_code)
- logging.info(response)
- url = "https://sc.ftqq.com / 你的 SCKEY.send?text=douban 失败" + \
- str(random.randint(0, 1000))
- requests.post(url)
- logging.info("豆瓣 ding 失败, 发送失败信息到微信")
- # 豆瓣顶帖
- def douban_ding():
- # 豆瓣具体帖子
- url = "https://www.douban.com/group/topic/129122199/"
- # 豆瓣具体帖子回复的接口, 格式是帖子链接 +/add_comment
- comment_url = url + "/add_comment"
- cookie = 'cookie'
- referer = url
- agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
- headers = {
- "Host": "www.douban.com",
- "Referer": referer,
- 'User-Agent': agent,
- "Cookie": cookie
- }
- params = {
- "rv_comment": '',
- "ck": re.findall("ck=(.*?);", headers["Cookie"])[-1],
- 'start': '0',
- 'submit_btn': '发送'
- }
- response = requests.get(url, headers=headers, verify=False).content.decode('utf-8')
- selector = HTML.fromstring(response)
- captcha_image = selector.xpath("//img[@id=\"captcha_image\"]/@src")
- if captcha_image:
- logging.info("发现验证码, 下载验证码")
- captcha_id = selector.xpath("//input[@name=\"captcha-id\"]/@value")
- filename = download_captcha(captcha_image[0], agent)
- captcha_solution = recognition_captcha(filename, 1006)
- os.remove(filename)
- params['captcha-solution'] = captcha_solution
- params['captcha-id'] = captcha_id
- else:
- logging.info("没有验证码")
- response = requests.post(comment_url, headers=headers, allow_redirects=False,
- data=params, verify=False)
- result_verification(response)
- if __name__ == '__main__':
- douban_ding()
运行结果:
第 1 次:
2018-12-30 16:09:35.589 INFO: 没有验证码
2018-12-30 16:09:36.436 INFO: 豆瓣 ding 成功
第 4 次:
2018-12-30 16:13:02.135 INFO: 发现验证码, 下载验证码
2018-12-30 16:13:02.135 INFO: 文件名为: douban_OJGsVa0hST4O2WhFA0VpMnR9.jpg
2018-12-30 16:13:02.554 INFO: douban_OJGsVa0hST4O2WhFA0VpMnR9.jpg 下载完成
2018-12-30 16:13:09.687 INFO: 豆瓣 ding 成功
效果图:
注:
顶帖的时候控制好频率, 不然容易被禁言.
豆瓣禁言
来源: https://juejin.im/post/5c2cb3d5e51d452baa77fbf9