在豆瓣上帮小姐姐的租房帖顶帖。

顶帖不易,于是想到用python调用接口自动顶帖。

通过分析网络接口数据抓到豆瓣上[发表评论]的接口为

其中xxxxx 为小组里所发帖子的唯一ID,位置如下


有了第一步,就开始写代码。引入python的requests库轻松就调用成功了。

很顺利的过程。

写成定时任务,通过schedule模块定时30秒刷一个。

很顺利的过程+1。

没运行多久就出现了问题,接口返回200。 去看了看页面,原来是有个验证码需要验证。

不过这也难不到我们不是,为了给小姐姐顶帖只能迎难而上。

鄙人观察了一下验证码都是英文字母,这里介绍一个验证码试别工具:百度的文字识别API。

具体代码后面贴出。这里不详细叙述。传入的是一张图片流,输出的是这张图片里所含的文字信息。(这里文字信息泛指一切符号,不要想得很美好,都是英文字母返回,后面使用的时候吃过亏)

页面的验证码图片还是通过解析 评论接口 的返回html数据获得。通过简单的正则匹配就可以轻松获得。拿到图片意味着我们可以通过百度文字试别API获取到图片的文字信息了。没错,验证码的参数值搞定了,传入接口,一顿操作后。

很顺利的过程+2。

然而这就完了吗,好景不长,发现虽然能通过验证码评论成功了。但是还是失败率极高。我就想啊,或许是试别的验证码和实际图片里呈现的不符。 打印出图片的URL,肉眼比对和文字识别的结果。 虽然最终证实是不一样的,但是当时没仔细一下子发现,愣是看了很久。原因就是前面的一个伏笔,识别的是文字符号不只是英文,仔细看图片里面黑色的背景或者偏白色的部分会被识别为一个"." 点号或者一个空格。 当时打印了结果但是一个空格且是在单词的结尾无法分辨是否存在,直到出现一个点才看的清楚。尼玛,总算找到原因了,改完继续跑。

很顺利的过程+2.5。

为什么这里是2.5呢,因为又tm好景不长,玩过爬虫的人都会遇到封IP甚至封号的情况,所以在刷了一个下午之后,我就被系统制裁了。


Python比对list python比对两个图片的文字_API


最后我还是解封了,但是最好不要用自己的号去刷,可以申请小号去尝试。

当然最后也帮小姐姐找到租友了。

speak is cheap,show me the code。

所以最后贴上代码。


# encoding: utf-8
import urllib.request
import requests
import time
import schedule
import datetime
import json
from aip import AipOcr
import ssl
import re
from io import BytesIO

# ssl._create_default_https_context = ssl._create_unverified_context  # 取消全局验证

verify_IMG_ID = "img_code"
img_url = ""
refer = "https://www.douban.com/group/topic/133599338/?start=0"  # 正常访问的refer


def job():
    global verify_IMG_ID, img_url, refer
    url = "https://www.douban.com/group/topic/133599338/add_comment"
    headers = {
        "Host": "www.douban.com",
        "Referer": refer,
        "Cookie": "cookie",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36"
    }
    current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    params = {
        "ck": "jhb4",
        "rv_comment": "up " + current_time,
        "start": 0,
        "img": "(binary)",
        "captcha-solution": text_identify(img_url).__str__(),  # 验证码的解析文本
        "captcha-id": verify_IMG_ID,  # 验证码图片ID
        "submit_btn": "发送"
    }

    """ 在豆瓣多次调用评论接口后会返回一个页面,需要输入验证码,从页面里我们解析dom信息拿到验证码图片的URL,然后读取成图片,解析文本"""

    response = requests.post(url, headers=headers, allow_redirects=False, data=params, verify=False)
    print(response)
    if response.__str__().__contains__("200"):  ## 需要验证码
        searchObj = re.search(r'(.*)(https://www.douban.com/misc/captcha)(.*?)(alt="captcha").*',
                              response.content.__str__(), re.M | re.I)
        img_url = searchObj.group(2) + searchObj.group(3)  # 图片URL
        print("imgURL->" + img_url)
        verify_IMG_ID = searchObj.group(3)[4:4 + 27]
        print("imgCode->" + verify_IMG_ID)
        refer = "https://www.douban.com/group/topic/133599338/add_comment" # 在需要验证码的时候接口的refer也变了


def text_identify(img_url):
    if img_url == '':
        return ""
    APP_ID = 'APP_ID'
    API_KEY = 'API_KEY'
    SECRET_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(u'C:UsersPCPicturestextimg.png')

    # 网络获取图片
    res = requests.get(img_url,
                       stream=True)  # 获取字节流最好加stream这个参数,原因见requests官方文档

    image = BytesIO(res.content).getvalue()

    """BaiduAPI文字试别"""
    result = client.basicAccurate(image)
    
    if "error_msg" in result.keys():
        print("图片解析错误:"+result['error_msg'])
        return ""
    print("BaiduAPI result>>" + str(result)) #调试
    if int(result['words_result_num']):
        text_plain = result["words_result"][0]["words"].strip().replace(".","")
        print("试别结果:%s" % text_plain)
        return text_plain  # 发现有"点号"或者"空格"被试别
    print("未试别:%s" % json.dumps(result))


if __name__ == '__main__':
    print("豆瓣刷评开始---")
    job()
    schedule.every(30).seconds.do(job) #每隔30秒刷一次
    while True:
        schedule.run_pending()
        time.sleep(1)