總結(jié)一下自己原創(chuàng)的一個(gè)爬取微信公眾號(hào)文章的方法。
未經(jīng)同意禁止轉(zhuǎn)載金闽,否則通過維權(quán)騎士追究
【源代碼請(qǐng)點(diǎn)擊 此處 留言以獲取】
之前在網(wǎng)上也搜索了些爬取微信公眾號(hào)的資料素跺,大概有如下幾種
Part1 需求分析
因?yàn)橹肮渲跻押ィ詹亓瞬簧賱e人推薦的數(shù)據(jù)分析、機(jī)器學(xué)習(xí)相關(guān)的微信公眾號(hào)澎嚣。
但是在手機(jī)上一頁(yè)頁(yè)的翻閱瀏覽疏尿,很不方便。所以想了想能否將這些公眾號(hào)文章下載下來
這樣的話易桃,看起來也方便褥琐。但是網(wǎng)上的方法要么太麻煩(對(duì)于我這個(gè)非爬蟲新手來說),要么付費(fèi)晤郑。
但我的需求其實(shí)卻很簡(jiǎn)單——“方便的查找瀏覽相關(guān)公眾號(hào)的任意文章”
所以敌呈,最后自己造了個(gè)輪子(雖然相當(dāng)?shù)图?jí),但好歹是自己一個(gè)一個(gè)鍵盤敲出來的==)
- 輸入:給定公眾號(hào)ID贩汉,和其在傳送門站點(diǎn)下的目錄頁(yè)碼數(shù)
- 輸出Ⅰ:每個(gè)公眾號(hào)對(duì)應(yīng)的文章記錄CSV文件
- 輸出Ⅱ: wkhtmltopdf和pdfkit將html轉(zhuǎn)換成PDF文件或者圖片文件
Part2 網(wǎng)上資料
以下幾種方法內(nèi)容整合自互聯(lián)網(wǎng)驱富,參考鏈接
如有侵權(quán),請(qǐng)聯(lián)系我刪減匹舞。
python爬取
1.需要安裝python selenium模塊包褐鸥,通過selenium中的webdriver驅(qū)動(dòng)瀏覽器獲取Cookie的方法、來達(dá)到登錄的效果赐稽;
2.使用webdriver功能需要安裝對(duì)應(yīng)瀏覽器的驅(qū)動(dòng)插件叫榕,我這里測(cè)試用的是谷歌瀏覽器:
google chrome版本為52.0.2743.6 ;
chromedriver版本為:V2.23
注意:谷歌瀏覽器版本和chromedriver需要對(duì)應(yīng),否則會(huì)導(dǎo)致啟動(dòng)時(shí)報(bào)錯(cuò)姊舵∥铮【附:selenium之 chromedriver與chrome版本映射表(更新至v2.30)http://blog.csdn.net/huilan_same/article/details/51896672)】3.微信公眾號(hào)登陸地址:https://mp.weixin.qq.com/
4.微信公眾號(hào)文章接口地址可以在微信公眾號(hào)后臺(tái)中新建圖文消息,超鏈接功能中獲壤ǘ :
5.搜索公眾號(hào)名稱
6.獲取要爬取的公眾號(hào)的fakeid
7.選定要爬取的公眾號(hào)荞下,獲取文章接口地址
8.文章列表翻頁(yè)及內(nèi)容獲取
AnyProxy代理批量采集
實(shí)現(xiàn)方法:anyproxy+js
實(shí)現(xiàn)方法:anyproxy+java+webmagic
FiddlerCore
實(shí)現(xiàn)方法:抓包工具,F(xiàn)iddler4
通過對(duì)多個(gè)賬號(hào)進(jìn)行抓包分析史飞,可以確定:
- _biz:這個(gè)14位的字符串是每個(gè)公眾號(hào)的“id”尖昏,搜狗的微信平臺(tái)可以獲得
- uin:與訪問者有關(guān),微信號(hào)id
- key:和所訪問的公眾號(hào)有關(guān)
步驟:
1构资,寫按鍵精靈腳本抽诉,在手機(jī)上自動(dòng)點(diǎn)擊公號(hào)文章列表頁(yè),也就是“查看歷史消息”吐绵;
2迹淌,使用fiddler代理劫持手機(jī)端的訪問,將網(wǎng)址轉(zhuǎn)發(fā)到本地用php寫的網(wǎng)頁(yè)己单;
3唉窃,在php網(wǎng)頁(yè)上將接收到的網(wǎng)址備份到數(shù)據(jù)庫(kù);
4荷鼠,用python從數(shù)據(jù)庫(kù)取出網(wǎng)址句携,然后進(jìn)行正常的爬取。
爬的過程中發(fā)現(xiàn)一個(gè)問題:
如果只是想爬取文章內(nèi)容允乐,似乎并沒有訪問頻率限制矮嫉,但如果想抓取閱讀數(shù)削咆、點(diǎn)贊數(shù),超過一定頻率后蠢笋,返回就會(huì)變?yōu)榭罩挡ζ耄以O(shè)定的時(shí)間間隔為10秒,可以正常抓取昨寞,這種頻率下瞻惋,一個(gè)小時(shí)只能抓取360條,已經(jīng)沒什么實(shí)際意義了援岩。
清博 新榜
如果只是想看數(shù)據(jù)的話歼狼,直接看每天的榜單就可以了,還不用花錢享怀,如果需要接入自己的系統(tǒng)的話羽峰,他們也提供api接口
Part3 項(xiàng)目步驟
基本原理
該網(wǎng)站收錄了絕大部分的微信公眾號(hào)文章,會(huì)定期更新添瓷,經(jīng)測(cè)試發(fā)現(xiàn)對(duì)爬蟲較為友好
網(wǎng)站頁(yè)面布局排版規(guī)律梅屉,不同公眾號(hào)通過http://chuansong.me/account/almosthuman2014
鏈接中的account
區(qū)分
一個(gè)公眾號(hào)合集下的文章翻頁(yè)也有規(guī)律:id號(hào)每翻一頁(yè)+12
所以思路大概就是
- 給定公眾號(hào)ID
- 獲取html
- 正則表達(dá)式提取目標(biāo)內(nèi)容
- 保存爬蟲結(jié)果(csv)
- 調(diào)用pdfkit和wkhtmltopdf轉(zhuǎn)換網(wǎng)頁(yè)
環(huán)境
- win10(64bit)
- Spyder(python3.6)
- 安裝wkhtmltopdf
相關(guān)包
- requests
- pdfkit
獲取頁(yè)面
def get_one_page(url):
#需要加一個(gè)請(qǐng)求頭部,不然會(huì)被網(wǎng)站封禁
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'}
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status #若不為200鳞贷,則引發(fā)HTTPError錯(cuò)誤
response.encoding = response.apparent_encoding
return response.text
except:
return "產(chǎn)生異常"
注意坯汤,目標(biāo)爬蟲網(wǎng)站必須要加headers,否則直接拒絕訪問
正則解析html
def parse_one_page(html):
pattern = re.compile('<div class="feed_item_question">.*?<span>.*?<a class="question_link" href="(.*?)".*?_blank">(.*?)</a>.*?"timestamp".*?">(.*?)</span>', re.S)
items = re.findall(pattern, html)
return items
自動(dòng)跳轉(zhuǎn)頁(yè)面
def main(offset, i):
url = 'http://chuansong.me/account/' + str(offset) + '?start=' + str(12*i)
print(url)
wait = round(random.uniform(1,2),2) # 設(shè)置隨機(jī)爬蟲間隔搀愧,避免被封
time.sleep(wait)
html = get_one_page(url)
for item in parse_one_page(html):
info = 'http://chuansong.me'+item[0]+','+ item[1]+','+item[2]+'\n'
info = repr(info.replace('\n', ''))
print(info)
#info.strip('\"') #這種去不掉首尾的“
#info = info[1:-1] #這種去不掉首尾的“
#info.Trim("".ToCharArray())
#info.TrimStart('\"').TrimEnd('\"')
write_to_file(info, offset)
去掉標(biāo)題中的非法字符
因?yàn)閣indows下文件命令惰聂,有些字符是不能用了,所以需要使用正則剔除
itle = re.sub('[\\\\/:*?\"<>|]', '', info.loc[indexs]['標(biāo)題'])
轉(zhuǎn)換html
使用pandas的read_csv函數(shù)讀取爬取的csv文件咱筛,循環(huán)遍歷“鏈接”,“標(biāo)題”庶近,“日期”
def html_to_pdf(offset):
wait = round(random.uniform(1,2),2) # 設(shè)置隨機(jī)爬蟲間隔,避免被封
time.sleep(wait)
path = get_path(offset)
path_wk = r'D:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe' #安裝wkhtmltopdf的位置
config = pdfkit.configuration(wkhtmltopdf = path_wk)
if path == "" :
print("尚未抓取該公眾號(hào)")
else:
info = get_url_info(offset)
for indexs in info.index:
url = info.loc[indexs]['鏈接']
title = re.sub('[\\\\/:*?\"<>|]', '', info.loc[indexs]['標(biāo)題'])
date = info.loc[indexs]['日期']
wait = round(random.uniform(4,5),2) # 設(shè)置隨機(jī)爬蟲間隔眷蚓,避免被封
time.sleep(wait)
print(url)
with eventlet.Timeout(4,False):
pdfkit.from_url(url, get_path(offset)+'\\'+ date+'_'+title+'.pdf', configuration=config)
print('轉(zhuǎn)換成功!')
結(jié)果展示
爬取結(jié)果
爬取的幾個(gè)公眾號(hào)分文件夾存儲(chǔ)
文件夾目錄下的內(nèi)容
爬取的CSV內(nèi)容格式
生成的PDF結(jié)果
遇到的問題
問題1
for item in parse_one_page(html):
info = 'http://chuansong.me'+item[0]+','+ item[1]+','+item[2]+'\n'
info = repr(info.replace('\n', ''))
info = info.strip('\"')
print(info)
#info.strip('\"') #這種去不掉首尾的“
#info = info[1:-1] #這種去不掉首尾的“
#info.Trim("".ToCharArray())
#info.TrimStart('\"').TrimEnd('\"')
write_to_file(info, offset)
解決辦法
字符串中首尾帶有“”,使用上文中的#注釋部分的各種方法都不好使反番,
最后的解決辦法是:
在寫入字符串的代碼出沙热,加上.strip('\'\"'),以去掉‘和”
with open(path, 'a', encoding='utf-8') as f: #追加存儲(chǔ)形式,content是字典形式
f.write(str(json.dumps(content, ensure_ascii=False).strip('\'\"') + '\n'))
f.close()
問題2
調(diào)用wkhtmltopdf.exe將html轉(zhuǎn)成pdf報(bào)錯(cuò)
調(diào)用代碼
``` python
path_wk = 'D:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'
config = pdfkit.configuration(wkhtmltopdf = path_wk)
pdfkit.from_url(url, get_path(offset)+'\\taobao.pdf', configuration=config)
```
報(bào)錯(cuò)信息
OSError: No wkhtmltopdf executable found: "D:\Program Files\wkhtmltopdin\wkhtmltopdf.exe"
If this file exists please check that this process can read it. Otherwise please install wkhtmltopdf - https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf
解決辦法
path_wk = r'D:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'
config = pdfkit.configuration(wkhtmltopdf = path_wk)
pdfkit.from_url(url, get_path(offset)+'\\taobao.pdf', configuration=config)
或者
path_wk = 'D:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe'
config = pdfkit.configuration(wkhtmltopdf = path_wk)
pdfkit.from_url(url, get_path(offset)+'\\taobao.pdf', configuration=config)
原因
Your config path contains an ASCII Backspace, the \b in \bin,
which pdfkit appears to be stripping out and converting D:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe
to D:\Program Files\wkhtmltopdf\wkhtmltopdf.exe.