1. 程式人生 > >50行程式碼教你打造一個公眾號文章採集器

50行程式碼教你打造一個公眾號文章採集器

640?wx_fmt=png

Alfred的女票是一枚資料科學領域的新媒體運營官(是的,Alfred是一名程式設計師,Alfred有女票640?),每天都要閱讀大量的行業相關文章,以掌握行業的動向,挑選和生產相關內容。為此,她關注了一大批的相關公眾號,每天都一個個公眾號挨個點開閱讀,怪麻煩的。

一來可能漏掉某些公眾號更新的重要訊息,二來經常會看到轉載的重複性的文章。

這可咋辦呢?

身為一個合(gao)格(shi)的男票,我是那個看在眼裡急在心裡啊!

那就寫一個公眾號文章的收集器吧,每天早上9點的時候都把昨天一天以來各個行業內公眾號發表的文章的標題、摘要和連結等相關資訊爬下來,形成一個文件發給女票,這樣可以大大方便閱讀。

就這麼愉快地決定了

需求很簡單,主要分為兩塊,一塊是公眾號文章爬取,一塊是把爬回來的文章儲存為word文件。

公眾號文章爬取

首先跟女票要了她關注的公眾號,結果她發我很長很長的一串列表,足足有50多個公眾號。算了算,如果每個公眾號每天更新3篇文章,那麼她每天最少就得看150多篇公眾號文章,確實是夠嗆呀。

接著是爬取公眾號文章。這方面早已有人造好了輪子,也就是基於搜狗微信搜尋的微信公眾號爬蟲介面:WechatSogou,在此感謝@Chyroc。 

傳送門:

https://github.com/Chyroc/WechatSogou

640?wx_fmt=png

也就是,我們不用自己造輪子,只需要呼叫API就好了。

wechatsogou 的使用很簡單,先例項化一個WechatSogouAPI,便可以呼叫get_gzh_article_by_history()方法返回最近10篇文章,比如說要爬取“Alfred在紐西蘭”的文章,便是:

ws_api = wechatsogou.WechatSogouAPI()
ws_api. get_gzh_article_by_history('Alfred在紐西蘭')

這樣便可以返回一個json檔案,裡面包含“Alfred在紐西蘭”公眾號的最近10篇文章。

640?wx_fmt=gif

這個輪子是不是嗖嗖的?

640?wx_fmt=png

可見,文章儲存在“article”對應的列表裡,相關的資訊有標題(title)、摘要(abstract)、文章連結(content_url)、發表時間(datetime)、是否頭條(main)、版權狀況(copyright_stat)等。

這就是說,只要例項化一個WechatSogouAPI,然後遍歷一下長長的公眾號列表,便可以把所有公眾號近期發表的文章爬取下來了。然後加一個時間過濾,便可獲得一天以來發表的文章。

640?wx_fmt=gif

當然,作為一個貼心的男票,我還加上了頭條文章過濾和原創文章過濾,預設把不是頭條和不是原創的文章都過濾掉,並把它封裝成一個function:

from datetime import *
import wechatsogou

# 文章爬取
def get_articles(headline=True, original=True, timedel=1, add_account=None):

  with open('gzh.txt', 'r') as f:
      accounts = [account.strip() for account in f.readlines()]
  # add_account必須是一個list或None
  if add_account is not None:
      if isinstance(list, add_account):
          accounts.extend(add_account)
          with open('gzh.txt', 'w') as f:
              for account in accounts:
                  f.write(account)
      else:
          print('add_account should be a list')

  ws_api = wechatsogou.WechatSogouAPI(captcha_break_time=3)
  articles = []
  for account in accounts:
      articles.extend(reformat(ws_api.get_gzh_article_by_history(account)))

  # 時間過濾,只選取規定天數以內的
  timestamp = int((datetime.now()-timedelta(days=timedel)).timestamp())
  articles = [article for article in articles if article['datetime'] > timestamp]

  # 頭條文章過濾,是否選取頭條文章,預設是
  if headline:
      articles = [article for article in articles if article['main'] == 1]

  # 原創文章過濾,是否選取原創文章,預設是
  if original:
      articles = [article for article in articles if article['copyright_stat'] == 100]

  return articles

# 為儲存每篇文章的字典新增一個公眾號來源
def reformat(data):
  atcs = data.get('article')
  if atcs is not None:
      wechat_name = data.get('gzh')['wechat_name']
      for article in atcs:
          article['wechat_name'] = wechat_name
      return atcs

儲存為word文件

最後爬回來的文章是一個list,裡面每個dict存放著每篇文章的資訊。我們需要把這個list儲存到word文件裡面,並且以一個清晰的排版呈現出來。

這時候有一個叫python-docx的庫,可以很方便的幫助我們來做這件事情。

傳送門:

https://python-docx.readthedocs.io/

Python-docx的使用也很簡單,例項化一個類,再通過add_headingd()的方法新增標題、add_paragraph()方法新增段落、add_picture()方法新增圖片,便可以按照我們的想法進行排版。例如:

from docx import Document
from docx.shared import Inches

document = Document()  # 例項化一個Document類
document.add_heading('這是一個標題', 0)  # 新增標題
document.add_paragraph('這是一段話')  # 新增段落
document.add_picture('一個圖片.jpeg', width=Inches(1))  新增圖片

上面一段程式碼生成的word文件長這樣:

640?wx_fmt=png

因此,遍歷一下爬回來的list,然後排版,儲存到本地,便大功告成了。

最後爬回來的文件開頭長這樣:

640?wx_fmt=png

結尾長這樣:

640?wx_fmt=png

撒狗糧成功!溜了~

640?wx_fmt=png

後記:

1.後期還可以為這個採集器加上更多的功能,比如說再新增一個把word以郵件形式直接傳送郵箱的功能,或者儲存為Excel的功能等,都是可以的;

2.當然也可以把它轉換成小程式,方便執行;

3.由於驗證碼識別的原因,有一些驗證碼需要人工識別,希望以後的wechatsougou可以更強大;

4.完整的程式碼可以在公眾號後臺回覆"公眾號文章"獲取。

640?wx_fmt=png

∞∞∞

640?wx_fmt=jpeg&wx_lazy=1

IT派 - {技術青年圈}持續關注網際網路、區塊鏈、人工智慧領域640?wx_fmt=jpeg&wx_lazy=1

公眾號回覆“Python”

邀你加入{ IT派Python技術群 }