国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

基于asyncio編寫一個(gè)telegram爬蟲機(jī)器人

馬忠志 / 2643人閱讀

摘要:而的異步非阻塞特性能夠完美的解決這一問(wèn)題。爬蟲機(jī)器人功能實(shí)現(xiàn)我使用編寫的機(jī)器人是用來(lái)抓取來(lái)自游民星空的圖片。也是使用裝飾器進(jìn)行回調(diào)函數(shù)注冊(cè),使用進(jìn)行消息更新。當(dāng)沒有指令時(shí),會(huì)顯示一些能夠查看的圖片類型。

原文鏈接

前言

aiotg 可以通過(guò)異步調(diào)用telegram api的方式來(lái)構(gòu)建bot,因?yàn)闆Q定開發(fā)一個(gè)爬蟲功能的bot,所以網(wǎng)絡(luò)請(qǐng)求阻塞是比較嚴(yán)重的性能障礙。而asyncio的異步非阻塞特性能夠完美的解決這一問(wèn)題。這篇文章在記錄如何使用aiotg進(jìn)行telegram開發(fā)的同時(shí),也會(huì)說(shuō)明一些aiohttp的使用方法,這里是項(xiàng)目源碼。如果你覺得不錯(cuò)可以幫忙點(diǎn)一下star

https://t.me/fpicturebot 點(diǎn)擊鏈接可以體驗(yàn)一下這個(gè)bot的功能。

如果讀者之前對(duì)telegram的bot沒有了解,可以查看這篇寫給開發(fā)者的telegram-bots介紹文檔

aiotg簡(jiǎn)單教程 1.一個(gè)最簡(jiǎn)單的bot

你可以先學(xué)習(xí)如何新建一個(gè)機(jī)器人

from aiotg import Bot, Chat

config = {
    "api_token": "***********",
    "proxy": "http://127.0.0.1:8118"
}

bot = Bot(**config)

@bot.command(r"/echo (.+)")
def echo(chat: Chat, match):
    return chat.reply(match.group(1))

bot.run()

上面是一個(gè)簡(jiǎn)單的回復(fù)機(jī)器人,當(dāng)你使用指令 /echo+內(nèi)容時(shí),機(jī)器人會(huì)自動(dòng)回復(fù)給你發(fā)送的內(nèi)容。這里要注意一點(diǎn),在我這里沒有采用使用 pipenv ( pip ) 安裝aiotg的方法,因?yàn)閜ip平臺(tái)上安裝的是master分支的包,aiotg通過(guò)使用aiohttp來(lái)調(diào)用telegram bot api,在創(chuàng)建一個(gè)bot的時(shí)候沒有提供proxy選項(xiàng)為aiohttp設(shè)置代理,在本地開發(fā)的時(shí)候會(huì)因?yàn)閲?guó)內(nèi)網(wǎng)絡(luò)抽搐出現(xiàn)網(wǎng)絡(luò)連接錯(cuò)誤,所以在這里我使用了aiotg的prxoy分支,直接從github上下載的代碼。在創(chuàng)建Bot對(duì)象的時(shí)候加入proxy選項(xiàng)就能使用本地代理來(lái)進(jìn)行開發(fā)調(diào)試了。

后來(lái)我在aiotg telegram群里建議作者將proxy合并到主分支,后來(lái)作者表示他也有這樣的想法,同時(shí)他也吐槽了一下俄羅斯的網(wǎng)絡(luò)也有很多審查和限制,現(xiàn)在在aiotg里已經(jīng)沒有proxy分支了,在aiotg-0.9.9版本中提供proxy選項(xiàng),所以大家可以繼續(xù)使用pipenv下載aiotg包。

2.aiotg異步特性

既然用到aiotg來(lái)開發(fā)就是看中了他的異步特性,下面就列出一個(gè)簡(jiǎn)單的例子

import aiohttp
import json
from aiotg import Bot, Chat

with open("token.conf") as f:
    token = json.loads(f.read())

bot = Bot(**token)

@bot.command("/fetch")
async def async_fecth(chat: Chat, match):
    url = "http://www.gamersky.com/ent/111/"
    async with aiohttp.ClientSession() as sesssion:
        async with sesssion.get(url) as resp:
            info = " version: {}
 status :{}
 method: {}
 url: {}
".format(
                resp.version, resp.status, resp.method, resp.url)
            await chat.send_text(info)

bot.run(debug=True)

3. 自定義鍵盤

關(guān)于自定義鍵盤的內(nèi)容可以點(diǎn)擊鏈接查看官方解釋,這里是簡(jiǎn)單的中文描述。

category.json

[
    {
        "name": "dynamic",
        "title": "動(dòng)態(tài)圖",
        "url": "http://www.gamersky.com/ent/111/"
    },
    {
        "name": "oops",
        "title": "囧圖",
        "url": "http://www.gamersky.com/ent/147/"
    },
    {
        "name": "beauty",
        "title": "福利圖",
        "url": "http://tag.gamersky.com/news/66.html"
    },
    {
        "name": "easy-moment",
        "title": "輕松一刻",
        "url": "http://www.gamersky.com/ent/20503/"
    },
    {
        "name": "trivia",
        "title": "冷知識(shí)",
        "url": "http://www.gamersky.com/ent/198/"
    },
    {
        "name": "cold-tucao",
        "title": "冷吐槽",
        "url": "http://www.gamersky.com/ent/20108/"
    }
]

main.py

import aiohttp
import json
from aiotg import Bot, Chat

with open("token.json") as t, open("category.json") as c:
    token = json.loads(t.read())
    category = json.loads(c.read())

bot = Bot(**token)

@bot.command("/reply")
async def resply(chat: Chat, match):
    kb = [[item["title"]] for item in category]
    keyboard = {
        "keyboard": kb,
        "resize_keyboard": True
    }
    await chat.send_text(text="看看你的鍵盤", reply_markup=json.dumps(keyboard))

bot.run(debug=True)

只需要在調(diào)用chat的發(fā)送消息函數(shù)中,指定 reply_markup 參數(shù),你就能個(gè)性化的設(shè)定用戶鍵盤, reply_markup 參數(shù)需要一個(gè)json對(duì)象,官方指定為ReplyKeyboardMarkup類型,其中keyboard需要傳遞一個(gè)KeyboardButton的數(shù)組。

每個(gè)keyboard的成員代表著鍵盤中的行,你可以通過(guò)修改每行中KeyboardButton的個(gè)數(shù)來(lái)排列你的鍵盤,比如我們讓鍵盤每行顯示兩個(gè)KeyboardButton,如下所示

@bot.command("/reply")
async def reply(chat: Chat, match):
    # kb = [[item["title"]] for item in category]
    kb, row = [], -1
    for idx, item in enumerate(category):
        if idx % 2 == 0:
            kb.append([])
            row += 1
        kb[row].append(item["title"])
    keyboard = {
        "keyboard": kb,
        "resize_keyboard": True
    }
    await chat.send_text(text="看看你的鍵盤", reply_markup=json.dumps(keyboard))

4. 內(nèi)聯(lián)鍵盤和消息更新

內(nèi)聯(lián)鍵盤的意思就是附著在消息上的鍵盤,內(nèi)聯(lián)鍵盤由內(nèi)聯(lián)按鈕組成,每個(gè)按鈕會(huì)附帶一個(gè)回調(diào)數(shù)據(jù),每次點(diǎn)擊按鈕之后會(huì)有對(duì)應(yīng)的回調(diào)函數(shù)處理。

@bot.command("/inline")
async def inlinekeyboard(chat: Chat, match):

    inlinekeyboardmarkup = {
            "type": "InlineKeyboardMarkup",
            "inline_keyboard": [
                [{"type": "InlineKeyboardButton",
                  "text": "上一頁(yè)",
                  "callback_data": "page-pre"},
                 {"type": "InlineKeyboardButton",
                  "text": "下一頁(yè)",
                  "callback_data": "page-next"}]
                ]
            }

    await chat.send_text("請(qǐng)翻頁(yè)", reply_markup=json.dumps(inlinekeyboardmarkup))

@bot.callback(r"page-(w+)")
async def buttonclick(chat, cq, match):
    await chat.send_text("You clicked {}".format(match.group(1)))

有時(shí)候我們想修改之前已經(jīng)發(fā)送過(guò)的消息內(nèi)容,例如當(dāng)用戶點(diǎn)擊了內(nèi)聯(lián)鍵盤,而鍵盤的功能是進(jìn)行翻頁(yè)更新消息的內(nèi)容。這時(shí)候我們可以使用 editMessageText 功能。例如點(diǎn)擊上面內(nèi)聯(lián)鍵盤中的上一頁(yè)按鈕,你可以看到消息的內(nèi)容被更改了。

@bot.callback(r"page-(w+)")
async def buttonclick(chat, cq, match):
    await chat.edit_text(message_id=chat.message["message_id"], text="消息被修改了")

5.內(nèi)聯(lián)請(qǐng)求模式

內(nèi)聯(lián)請(qǐng)求模式感覺更適合在群組中使用,在討論組中輸入@botname + 特定指令,輸入框的上方就會(huì)顯示查詢內(nèi)容,你可以返回給用戶文章類型、圖片類型或者其他類型的查詢信息。官網(wǎng)有更詳細(xì)的內(nèi)容。

@bot.inline
async def inlinemode(iq):
    results = [{
            "type": "article",
            "id": str(index),
            "title": article["title"],
            "input_message_content": { "message_text": article["title"]},
            "description": f"這里是{article["title"]}"
        } for index, article in enumerate(category)]
    await iq.answer(results)

我們?cè)O(shè)定當(dāng)用戶輸入內(nèi)聯(lián)指令時(shí),bot返回可以選擇的圖片種類,返回結(jié)果的類型是article類型,官方還提供了語(yǔ)音,圖片,gif,視頻,音頻。表情等類型,你可以根據(jù)自己的需要進(jìn)行選擇。

爬蟲機(jī)器人功能實(shí)現(xiàn)

我使用aiotg編寫的機(jī)器人是用來(lái)抓取來(lái)自游民星空的圖片。

1. 爬蟲功能

爬蟲功能的實(shí)現(xiàn)是用aiohttp發(fā)送web請(qǐng)求,使用beautifulsoup進(jìn)行html解析,核心代碼如下

import re
import aiohttp
from bs4 import BeautifulSoup


def aioget(url):
    return aiohttp.request("GET", url)


def filter_img(tag):
    if tag.name != "p":
        return False
    try:
        if tag.attrs["align"] == "center":
            for child in tag.contents:
                if child.name == "img" or child.name == "a":
                    return True
        return False
    except KeyError:
        if "style" in tag.attrs:
            return True
        else:
            return False
            
            
async def fetch_img(url):
    async with aioget(url) as resp:
        resp_text = await resp.text()
        content = BeautifulSoup(resp_text, "lxml")
        imgs = content.find(class_="Mid2L_con").findAll(filter_img)
        results = []
        for img in imgs:
            try:
                results.append({
                    "src":  img.find("img").attrs["src"],
                    "desc": "
".join(list(img.stripped_strings))
                })
            except AttributeError:
                continue
        return results

我將aiohttp的get請(qǐng)求稍微包裝了一下,簡(jiǎn)潔一些。html中元素的提取就不在贅述,就是找找html中的規(guī)律

2. 指令功能

指令功能實(shí)現(xiàn)需要使用aiotg.bot.command裝飾器進(jìn)行命令注冊(cè),下面列出 /start的功能實(shí)現(xiàn)

@bot.command(r"/start")
async def list_category(chat: Chat, match):
    kb, row = [], -1
    for idx, item in enumerate(category["name"]):
        if idx % 2 == 0:
            kb.append([])
            row += 1
        kb[row].append(item)
    keyboard = {
        "keyboard": kb,
        "resize_keyboard": True
    }
    await chat.send_text(text="請(qǐng)選擇你喜歡的圖片類型", reply_markup=json.dumps(keyboard))

關(guān)于自定義鍵盤部分在上文中已經(jīng)講過(guò),讀者可以自己編碼實(shí)現(xiàn)

3. callback功能

讀者可以看到在消息上附有頁(yè)面切換按鈕,每個(gè)按鈕會(huì)帶著一個(gè)callbackdata,當(dāng)點(diǎn)擊按鈕會(huì)調(diào)用相應(yīng)的callback函數(shù)進(jìn)行處理,這里點(diǎn)擊下一頁(yè)時(shí)會(huì)進(jìn)行翻頁(yè)。

看頁(yè)面更新了,關(guān)于更新頁(yè)面的實(shí)現(xiàn)在上面也講到了如何進(jìn)行消息更新。

@bot.callback(r"page-(?Pw+)-(?Pd+)")
async def change_lists(chat: Chat, cq, match):
    req_name = match.group("name")
    page = match.group("page")
    url = category[req_name]
    text, markup = await format_message(req_name, url, page)
    await chat.edit_text(message_id=chat.message["message_id"], text=text, markup=markup)

也是使用裝飾器進(jìn)行回調(diào)函數(shù)注冊(cè),使用chat.edit_text進(jìn)行消息更新。

callback功能也用在了圖片的更新。點(diǎn)擊下一頁(yè)更新圖片。

4.內(nèi)聯(lián)請(qǐng)求模式功能

當(dāng)用戶在輸入框中輸入@botusername+指令時(shí),會(huì)在輸入框上顯示查詢內(nèi)容。

當(dāng)沒有指令時(shí),會(huì)顯示一些能夠查看的圖片類型。

當(dāng)輸入對(duì)應(yīng)類型漢字的前幾個(gè)字時(shí),bot會(huì)匹配你想看的圖片列表,并羅列出來(lái)

@bot.inline(r"([u4e00-u9fa5]+)")
async def inline_name(iq, match):
    req = match.group(1)
    req_name = match_category(req.strip(), category["name"])
    ptype = "G" if req_name == "dynamic" else "P"
    if req_name is None:
        return
    results, _ = await fetch_lists(category[req_name])
    c_results = [{
            "type": "article",
            "id": str(index),
            "title": item["title"],
            "input_message_content": {
                "message_text": "/" + ptype + item["date"] + "_" + item["key"]
            },
            "description": item["desc"]
        } for index, item in enumerate(results)]
    await iq.answer(c_results)
redis緩存

當(dāng)發(fā)送給用戶圖片時(shí),telegram會(huì)返回一個(gè)和圖片對(duì)應(yīng)的file_id, 當(dāng)再次發(fā)送相同的圖片時(shí),只需要在調(diào)用send_photo時(shí),將photo參數(shù)賦值為file_id即可,所以每次使用爬蟲進(jìn)行抓取圖片時(shí),將圖片的fild_id存在redis中,用戶請(qǐng)求圖片時(shí),如果圖片之前已經(jīng)抓取過(guò),這時(shí)候只要從redis中取出file_id,再調(diào)用send_photo即可。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/41774.html

相關(guān)文章

  • 關(guān)于Python爬蟲種類、法律、輪子的一二三

    摘要:一般用進(jìn)程池維護(hù),的設(shè)為數(shù)量。多線程爬蟲多線程版本可以在單進(jìn)程下進(jìn)行異步采集,但線程間的切換開銷也會(huì)隨著線程數(shù)的增大而增大。異步協(xié)程爬蟲引入了異步協(xié)程語(yǔ)法。 Welcome to the D-age 對(duì)于網(wǎng)絡(luò)上的公開數(shù)據(jù),理論上只要由服務(wù)端發(fā)送到前端都可以由爬蟲獲取到。但是Data-age時(shí)代的到來(lái),數(shù)據(jù)是新的黃金,毫不夸張的說(shuō),數(shù)據(jù)是未來(lái)的一切。基于統(tǒng)計(jì)學(xué)數(shù)學(xué)模型的各種人工智能的出現(xiàn)...

    lscho 評(píng)論0 收藏0
  • Python

    摘要:最近看前端都展開了幾場(chǎng)而我大知乎最熱語(yǔ)言還沒有相關(guān)。有關(guān)書籍的介紹,大部分截取自是官方介紹。但從開始,標(biāo)準(zhǔn)庫(kù)為我們提供了模塊,它提供了和兩個(gè)類,實(shí)現(xiàn)了對(duì)和的進(jìn)一步抽象,對(duì)編寫線程池進(jìn)程池提供了直接的支持。 《流暢的python》閱讀筆記 《流暢的python》是一本適合python進(jìn)階的書, 里面介紹的基本都是高級(jí)的python用法. 對(duì)于初學(xué)python的人來(lái)說(shuō), 基礎(chǔ)大概也就夠用了...

    dailybird 評(píng)論0 收藏0
  • 基于 asyncio 的Python異步爬蟲框架

    摘要:輕量異步爬蟲框架,基于,目的是讓編寫單頁(yè)面爬蟲更方便更迅速,利用異步特性讓爬蟲更快減少在上的耗時(shí)介紹對(duì)于單頁(yè)面,只要實(shí)現(xiàn)框架定義的就可以實(shí)現(xiàn)對(duì)目標(biāo)數(shù)據(jù)的抓取對(duì)于頁(yè)面目標(biāo)較多,需要進(jìn)行深度抓取時(shí),就派上用場(chǎng)了支持的加載類也可以很好的 aspider A web scraping micro-framework based on asyncio. 輕量異步爬蟲框架aspider,基于asy...

    Vultr 評(píng)論0 收藏0
  • 談?wù)剬?duì)Python爬蟲的理解

    摘要:爬蟲也可以稱為爬蟲不知從何時(shí)起,這門語(yǔ)言和爬蟲就像一對(duì)戀人,二者如膠似漆,形影不離,你中有我我中有你,一提起爬蟲,就會(huì)想到,一說(shuō)起,就會(huì)想到人工智能和爬蟲所以,一般說(shuō)爬蟲的時(shí)候,大部分程序員潛意識(shí)里都會(huì)聯(lián)想為爬蟲,為什么會(huì)這樣,我覺得有兩個(gè) 爬蟲也可以稱為Python爬蟲 不知從何時(shí)起,Python這門語(yǔ)言和爬蟲就像一對(duì)戀人,二者如膠似漆 ,形影不離,你中有我、我中有你,一提起爬蟲,就...

    Yang_River 評(píng)論0 收藏0
  • 基于asyncio、aiohttp、xpath的異步爬蟲

    摘要:今天介紹一下基于和的異步爬蟲的編寫,解析用的是。通過(guò)輸入問(wèn)題,該爬蟲能爬取關(guān)于健康方面的數(shù)據(jù)。先讀取規(guī)則,再爬取數(shù)據(jù)。 今天介紹一下基于asyncio和aiohttp的異步爬蟲的編寫,解析html用的是xpath。 該爬蟲實(shí)現(xiàn)了以下功能:1.讀取csv文件中的爬取規(guī)則,根據(jù)規(guī)則爬取數(shù)據(jù);代碼中添加了對(duì)3個(gè)網(wǎng)站的不同提取規(guī)則,如有需要,還可以繼續(xù)添加;2.將爬取到的數(shù)據(jù)保存到mysql數(shù)...

    ckllj 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<