日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

python使用pywinauto驅動微信客戶端實現公眾號爬蟲

瀏覽:2日期:2022-06-19 10:34:14
目錄項目地址pywinauto簡介WechatAutomator類init_windowcrawl_gongzhonghaolocate_userprocess_page項目地址

https://github.com/fancyerii/wechat-gongzhonghao-crawler

pywinauto簡介

pywinauto是一個python的工具,可以用于控制Windows的GUI程序。詳細的文檔可以參考這里。

WechatAutomator類

自動化微信的代碼封裝在了類WechatAutomator里,完整的代碼可以參考這里。這里簡要的介紹一下其中的主要方法:

init_window

這個方法完成類的初始化,它的代碼為:

def init_window(self, exe_path=r'C:Program Files (x86)TencentWeChatWeChat.exe', turn_page_interval=3, click_url_interval=1, win_width=1000, win_height=600):app = Application(backend='uia').connect(path=exe_path)self.main_win = app.window(title=u'微信', class_name='WeChatMainWndForPC')self.main_win.set_focus()self.app = appself.visible_top = 70self.turn_page_interval = turn_page_intervalself.click_url_interval = click_url_intervalself.browser = Noneself.win_width = win_widthself.win_height = win_height# 為了讓移動窗口,同時使用非uia的backend,這是pywinauto的uia的一個bugself.app2 = Application().connect(path=exe_path)self.move_window()

我們首先來看函數的參數:

exe_path 微信程序的地址 turn_page_interval 抓取翻頁時的時間間隔,默認3s click_url_interval 在抓取一頁的url時的間隔,默認1s win_width 設置窗口的寬度 win_height 設置窗口的高度,如果顯示器的分辨率較大,可以設置的更加高一些,從而一頁包含的文章數更多一些,從而翻頁少一點。注意:一定要保證窗口完全可見,也就是說win_height不能大于實際分辨率的高度!

這個函數的主要功能是構建Application對象從而通過pywinauto實現控制,這里使用的是uia的backend,然后設置窗口的大小并且把窗口移到最左上角。因為根據so文章,pywinauto 0.6.8存在bug,只能通過win32的backend來移到窗口,所以構造了self.app2然后調用move_window()函數把窗口移到最左上角。

crawl_gongzhonghao

這個函數實現了某個公眾號的文章抓取。它的基本控制邏輯如下:

首先通過搜索框根據名字搜索公眾號并且點擊它。 對于當前頁點擊所有的鏈接并且下載其內容。 使用PAGE_DOWN鍵往下翻頁 需要判斷是否繼續抓取

第一個是通過locate_user函數實現,后面會介紹。第二個是通過process_page函數實現,后面也會介紹。判斷是否繼續抓取的邏輯為:

如果翻頁超過max_pages,則停止抓取 如果碰到某個url曾經抓取過,那說明之前的文章都已經抓取過了,則停止抓取 如果lastest_date不是None并且一篇文章的發布日期早于它,則停止抓取

所以我們通常會在第一次抓取的時候把max_pages設置的很大(比如100),然后通過latest_date來抓到指定的日期。而之后的抓取則設置max_pages為較小的值(比如默認的6),這樣只要爬蟲在兩次抓取之間公眾號的更新不超過6頁,那么就不會漏掉文章。具體的邏輯可以參考main.py,它會把抓取的文章通過http請求發給Server,并且每次抓取的時候從Server查詢抓取過的文章存放到states這個list里states[i][“url”]就存儲了第i篇文章的url。

def crawl_gongzhonghao(self, account_name, articles, states, detail, max_pages=6, latest_date=None, no_item_retry=3):logger.debug(account_name)if not self.locate_user(account_name): return Falselast_visited_titles = set()visited_urls = set()self.turn_page_up(min(20, max_pages * 2))pagedown_retry = 0last_visited_titles = []for page in range(0, max_pages): items = [] last_visited_titles = self.process_page(account_name, items, last_visited_titles, states, visited_urls, detail) articles.extend(items) if len(items) == 0:pagedown_retry += 1if pagedown_retry >= no_item_retry: s = 'break because of retry {}'.format(pagedown_retry) logger.debug(s) WechatAutomator.add_to_detail(s, detail) break else:pagedown_retry = 0 if len(items) > 0 and latest_date is not None:html = items[-1][-1]pub_date = WechatAutomator.get_pubdate(html)if pub_date and pub_date < latest_date: s = 'stop because {} < {}'.format(pub_date, latest_date) logger.debug(s) WechatAutomator.add_to_detail(s, detail) break url_exist = False for item in items:if WechatAutomator.url_in_states(item[0], states): s = 'stop because url exist {}'.format(item[0]) logger.debug(s) WechatAutomator.add_to_detail(s, detail) url_exist = True break if url_exist:break self.click_right() self.main_win.type_keys('{PGDN}') time.sleep(self.turn_page_interval)self.turn_page_up(page * 2)return Truelocate_user

locate_user函數的控制流程為:

找到左上角的搜索框并且點擊它獲得焦點 使用ctrl+a選中可能有的文字(之前的bug?)并且使用后退鍵刪除它們 輸入公眾號名稱 在彈出的list里點擊這個公眾號名稱從而進入公眾號

def locate_user(self, user, retry=5):if not self.main_win: raise RuntimeError('you should call init_window first')search_btn = self.main_win.child_window(title='搜索', control_type='Edit')self.click_center(search_btn)self.main_win.type_keys('^a')self.main_win.type_keys('{BACKSPACE}')self.main_win.type_keys(user)for i in range(retry): time.sleep(1) try:search_list = self.main_win.child_window(title='搜索結果')match_result = search_list.child_window(title=user, control_type='ListItem')self.click_center(match_result)return True except:passreturn False

這里主要就是通過child_window函數進行定位,關于它的用法這里不介紹。關于怎么定位元素的方法可以使用Inspect.exe或者print_control_identifiers函數,具體參考這里。

process_page

這個函數是最主要的抓取代碼,它處理當前一頁的內容,它的控制流程如下:

構建當前頁的tree 使用recursive_get函數遍歷這顆樹并且找到每篇文章對應的element 遍歷每一篇文章 如果文章的名字在上一頁出現過,則跳過獲得這篇文章的坐標信息如果文章不可見(rect.top >= win_rect.bottom or rect.bottom <= self.visible_top)則跳過計算點擊的坐標點擊文章打開新的窗口在新的窗口中點擊【復制鏈接】按鈕從剪貼板復制鏈接url通過url下載文章內容并且parse發布日期

邏輯比較簡單,但是有一些很trick的地方:

微信翻頁的實現 微信客戶端的翻頁和瀏覽器不同,它的內容是累加的,比如第一頁3篇文章,往下翻一頁可能變成6篇文章,再翻可能變成9篇。這個時候這9篇文章都是在tree中的,只不過最后3篇的坐標(top和bottom)是空間的。 能否點擊 一篇文章對應的框(圖)可能是部分可見的,甚至它的top非常接近屏幕的最下方,這個時候可能點不了。如下圖所示:

python使用pywinauto驅動微信客戶端實現公眾號爬蟲

與此類似的是右上角的黑色頭部(不能滾到并且會遮擋)也有一定空間,如下圖所示:

python使用pywinauto驅動微信客戶端實現公眾號爬蟲

點擊的位置

因為這個框可能很窄(bottom-top很小)并且可能在很靠上或者靠下的位置。所以有如下代碼:

# 計算可見的高度 visible_height = min(rect.bottom, win_rect.bottom) - max(rect.top, win_rect.top+self.visible_top) # 太窄的不點擊,希望下次翻頁后能顯示更多像素從而可以點擊, # 但是如果微信的某個文章的框的高度小于10個像素,那么這篇文章就無法被點擊 # 不過作者目前為發現這么窄的文章 if visible_height < 10:continue# 如果某個文章的框太大,則拋出異常,目前為止為發現這樣的問題。 if rect.bottom - rect.top >= win_rect.bottom - self.visible_top:raise RuntimeError('{}-{}>={}-{}'.format(rect.bottom, rect.top, win_rect.bottom, self.visible_top)) # 如果下部部分可見,那么點擊上方是比較”安全“的 if rect.bottom >= win_rect.bottom:click_up = True # 如果下部完全可見,則點擊下方是”安全“的 else:click_up = False

完整代碼如下:

def process_page(self, account_name, items, lastpage_clicked_titles, states, visited_urls, detail):clicked_titles = set()text = self.main_win.child_window(title=account_name, control_type='Text', found_index=0)parent = textwhile parent: parent = parent.parent() if ’會話列表’ == parent.element_info.name:breakpaths = [0, 2, 0, 0, 0, 1, 0]for idx in paths: parent = parent.children()[idx]elems = []self.recursive_get(parent, elems)win_rect = self.main_win.rectangle()for elem in elems: rect = elem.rectangle() if elem.element_info.name in lastpage_clicked_titles:continue if rect.top >= win_rect.bottom or rect.bottom <= self.visible_top:continue visible_height = min(rect.bottom, win_rect.bottom) - max(rect.top, win_rect.top+self.visible_top) if visible_height < 10:continue if rect.bottom - rect.top >= win_rect.bottom - self.visible_top:raise RuntimeError('{}-{}>={}-{}'.format(rect.bottom, rect.top, win_rect.bottom, self.visible_top)) if rect.bottom >= win_rect.bottom:click_up = True else:click_up = False if self.is_bad_elem(elem):s = 'not good elem {}'.format(elem.element_info.name[0:10])logger.debug(s)WechatAutomator.add_to_detail(s, detail)continue try:self.click_url(rect, win_rect, click_up)copy_btn = self.browser.child_window(title='復制鏈接地址')self.click_center(copy_btn, click_main=False)url = clipboard.GetData()if elem.element_info.name != ’圖片’: clicked_titles.add(elem.element_info.name)if url and not url in visited_urls: visited_urls.add(url) html = None try:html = requests.get(url).text except:s = 'fail get {}'.format(url)logger.debug(s)WechatAutomator.add_to_detail(s, detail) items.append((url, rect, elem.element_info.name, html)) except:traceback.print_exc()pass finally:if self.browser: try:self.browser.close() except:pass self.browser = None time.sleep(self.click_url_interval)return clicked_titles

以上就是python使用pywinauto驅動微信客戶端實現公眾號爬蟲的詳細內容,更多關于python 公眾號爬蟲的資料請關注好吧啦網其它相關文章!

標簽: 微信 Python
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
午夜亚洲一区| 国产成人精品三级高清久久91| 欧美日韩四区| 最新亚洲国产| 国产精品一区高清| 97国产成人高清在线观看| 久久久一二三| 免费不卡在线观看| 日韩毛片一区| jizzjizz中国精品麻豆| 亚洲四虎影院| 亚洲少妇一区| 国产精品网站在线看| 日韩欧美中文| 最新国产精品视频| 丰满少妇一区| 亚洲少妇诱惑| 精品一区二区三区的国产在线观看 | 欧美成人久久| 天堂久久av| 国产精品毛片久久| 亚洲深夜av| 麻豆久久久久久| 免费欧美一区| 国产精品成人一区二区网站软件| 久久国产亚洲精品| 日本精品国产| 国产专区一区| 久久av超碰| 亚洲欧美视频一区二区三区| 麻豆国产欧美日韩综合精品二区| 黄色成人91| 国产精品xxx| 国产亚洲精品久久久久婷婷瑜伽| 美女在线视频一区| 男人的天堂亚洲一区| 国产不卡精品在线| 亚洲专区视频| 久久久成人网| 欧美成a人片免费观看久久五月天| 亚洲精品网址| 老司机精品在线| 伊人久久大香伊蕉在人线观看热v| 成人影视亚洲图片在线| 91国内精品| 欧美一级专区| 久久精品电影| 久久久国产精品网站| 亚洲一区二区日韩| 欧美日韩在线网站| 久久这里只有| 日韩激情精品| 久久国产精品亚洲77777| 日韩在线精品| 精品网站aaa| 欧美视频精品全部免费观看| 鲁大师成人一区二区三区| 亚洲四虎影院| 91视频一区| 国产精品qvod| 亚洲+小说+欧美+激情+另类| 怡红院精品视频在线观看极品| 红杏一区二区三区| 五月国产精品| 亚洲免费网址| 狠狠操综合网| 亚洲成人不卡| 精品久久久久中文字幕小说| 欧美日本不卡| 亚洲综合小说| 香蕉精品999视频一区二区| 99视频精品全部免费在线视频| 国产一区二区精品福利地址| 国产精品一区二区三区av麻| 日本成人在线视频网站| 蜜臀av国产精品久久久久| 久久中文字幕av| 黄色aa久久| 精品国产网站| 国产精久久一区二区| 欧美欧美黄在线二区| 午夜电影一区| 日韩精品高清不卡| 亚洲精品日韩久久| 综合色一区二区| 中文字幕日韩亚洲| 免费看日韩精品| 热久久国产精品| 免费在线看一区| 在线观看亚洲精品福利片| 日韩影院精彩在线| 美国三级日本三级久久99 | 欧美亚洲国产一区| 国产精品99精品一区二区三区∴| 亚洲制服一区| 欧美在线网站| 免费污视频在线一区| 精品日韩一区| 国产精品流白浆在线观看| 综合激情五月婷婷| 99久久夜色精品国产亚洲1000部| 91青青国产在线观看精品| 麻豆精品视频在线观看免费| 91精品国产自产精品男人的天堂 | 一区在线免费| 免费不卡中文字幕在线| 欧美日韩免费看片| 中文字幕在线视频网站| 久久亚洲道色| 欧美极品中文字幕| 欧美日韩91| 婷婷综合福利| 中文不卡在线| 日韩影院精彩在线| 国产精品7m凸凹视频分类| 精品日韩视频| 丝袜av一区| 久久一区二区三区喷水| 天堂日韩电影| 久久一区二区三区电影| 91中文字幕精品永久在线| 毛片不卡一区二区| 久久麻豆视频| 欧美好骚综合网| 91亚洲一区| 国产精品亚洲一区二区三区在线观看| аⅴ资源天堂资源库在线| 国产aa精品| 国产在线观看www| 荡女精品导航| 日韩黄色大片| 久久网站免费观看| 激情婷婷久久| 亚洲一区成人| 丝袜诱惑制服诱惑色一区在线观看| 久久精品免费一区二区三区 | 激情久久99| 欧美日韩国产v| 欧美一区二区三区激情视频| 一区视频在线| 日韩精品乱码av一区二区| 国产私拍福利精品视频二区| 国产伦精品一区二区三区在线播放 | 天堂√中文最新版在线| 色爱综合av| 麻豆精品网站| 日本欧美大码aⅴ在线播放| 国产欧美日韩视频在线| 91一区二区三区四区| 婷婷综合五月| 日韩精品免费视频人成| 精品免费视频| 999国产精品视频| 亚洲综合三区| 中文字幕日韩欧美精品高清在线| 欧美久久精品| 欧美好骚综合网| 亚洲欧美日本日韩| 国产日产一区| 日韩欧美一区二区三区免费看| 悠悠资源网久久精品| 色综合视频一区二区三区日韩| 欧美激情精品| 1024精品久久久久久久久| 亚洲精品一级| 国语精品一区| 99riav1国产精品视频| 日韩一区二区三区高清在线观看| 国产精品国产三级在线观看| 精品淫伦v久久水蜜桃| 国产字幕视频一区二区| 麻豆视频久久| 美女国产精品| 蜜臀国产一区| 久久国产视频网| 婷婷激情图片久久| 精品国产亚洲一区二区三区| 在线看片日韩| 久久精品国产www456c0m| 国产精品一区二区中文字幕| 国产精品女主播一区二区三区| 国产成人精品亚洲线观看| 日韩精品免费视频一区二区三区 | 免费观看日韩电影| 日韩在线中文| 麻豆91小视频| 日本午夜精品一区二区三区电影 | 亚洲成人va| 国产精品videossex久久发布| 亚洲一区国产一区| 欧洲亚洲一区二区三区| 久久99视频| 欧美日韩99| 亚洲综合精品| 久久精品1区| 亚洲欧洲高清| 麻豆极品一区二区三区| 日本欧美在线| 视频一区二区三区入口| 欧美/亚洲一区|