問題描述
利用搜狗的微信搜索抓取指定公眾號的最新一條推送,并保存相應的網(wǎng)頁至本地。
注意點
- 搜狗微信獲取的地址為
臨時鏈接
赵辕,具有時效性履因。 - 公眾號為動態(tài)網(wǎng)頁(
JavaScript
渲染),使用requests.get()
獲取的內(nèi)容是不含推送消息的馒铃,這里使用selenium+PhantomJS
處理
代碼
#! /usr/bin/env python3
from selenium import webdriver
from datetime import datetime
import bs4, requests
import os, time, sys
# 獲取公眾號鏈接
def getAccountURL(searchURL):
res = requests.get(searchURL)
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text, "lxml")
# 選擇第一個鏈接
account = soup.select('a[uigs="account_name_0"]')
return account[0]['href']
# 獲取首篇文章的鏈接蟹腾,如果有驗證碼返回None
def getArticleURL(accountURL):
browser = webdriver.PhantomJS("/Users/chasechoi/Downloads/phantomjs-2.1.1-macosx/bin/phantomjs")
# 進入公眾號
browser.get(accountURL)
# 獲取網(wǎng)頁信息
html = browser.page_source
accountSoup = bs4.BeautifulSoup(html, "lxml")
time.sleep(1)
contents = accountSoup.find_all(hrefs=True)
try:
partitialLink = contents[1]['hrefs']
firstLink = base + partitialLink
except IndexError:
firstLink = None
print('CAPTCHA!')
return firstLink
# 創(chuàng)建文件夾存儲html網(wǎng)頁痕惋,以時間命名
def folderCreation():
path = os.path.join(os.getcwd(), datetime.now().strftime('%Y-%m-%d_%H-%M-%S'))
try:
os.makedirs(path)
except OSError as e:
if e.errno != errno.EEXIST:
raise
print("folder not exist!")
return path
# 將html頁面寫入本地
def writeToFile(path, account, title):
pathToWrite = os.path.join(path, '{}_{}.html'.format(account, title))
myfile = open(pathToWrite, 'wb')
myfile.write(res.content)
myfile.close()
base ='https://mp.weixin.qq.com'
accountList = ['央視新聞', '新浪新聞','鳳凰新聞','羊城晚報']
query = 'http://weixin.sogou.com/weixin?type=1&s_from=input&query='
path = folderCreation()
for index, account in enumerate(accountList):
searchURL = query + account
accountURL = getAccountURL(searchURL)
time.sleep(10)
articleURL = getArticleURL(accountURL)
if articleURL != None:
print("#{}({}/{}): {}".format(account, index+1, len(accountList), accountURL))
# 讀取第一篇文章內(nèi)容
res = requests.get(articleURL)
res.raise_for_status()
detailPage = bs4.BeautifulSoup(res.text, "lxml")
title = detailPage.title.text
print("標題: {}\n鏈接: {}\n".format(title, articleURL))
writeToFile(path, account, title)
else:
print('{} files successfully written to {}'.format(index, path))
sys.exit()
print('{} files successfully written to {}'.format(len(accountList), path))
參考輸出
- Terminal輸出
- Finder
分析
鏈接獲取
- 首先進入搜狗的微信搜索頁面,在地址欄中提取需要的部分鏈接岭佳,字符串連接公眾號名稱血巍,即可生成請求鏈接
- 針對靜態(tài)網(wǎng)頁,利用
requests
獲取html文件珊随,再用BeautifulSoup
選擇需要的內(nèi)容 - 針對動態(tài)網(wǎng)頁述寡,利用
selenium+PhantomJS
獲取html文件,再用BeautifulSoup
選擇需要的內(nèi)容 - 遇到
驗證碼(CAPTCHA)
叶洞,輸出提示鲫凶。此版本代碼沒有對驗證碼做實際處理,需要人為訪問后衩辟,再跑程序螟炫,才能避開驗證碼。
文件寫入
- 使用
os.path.join()
構(gòu)造存儲路徑可以提高通用性艺晴。比如Windows
路徑分隔符使用back slash(\)昼钻, 而OS X
和Linux
使用forward slash
(/),通過該函數(shù)能根據(jù)平臺進行自動轉(zhuǎn)換封寞。 -
open()
使用b
(binary mode)參數(shù)同樣為了提高通用性(適應Windows
) - 使用
datetime.now()
獲取當前時間進行命名然评,并通過strftime()
格式化時間(函數(shù)名中的f代表format),具體使用參考下表(摘自 Automate the Boring Stuff with Python)
參考鏈接:
- 文件夾創(chuàng)建: https://stackoverflow.com/questions/14115254/creating-a-folder-with-timestamp
- 異常處理的使用: https://stackoverflow.com/questions/2574636/getting-a-default-value-on-index-out-of-range-in-python
-
enumerate
的使用: https://stackoverflow.com/questions/3162271/get-loop-count-inside-a-python-for-loop -
open()
使用b
參數(shù)理由: https://stackoverflow.com/questions/2665866/what-is-the-wb-mean-in-this-code-using-python