使用python爬取微信公众号文章

爬取前准备:

开发环境:Pycharm pycharm官网,(Community)社区版是免费的,(Professional)专业版是需要收费的,高校老师和学生是可以使用邮箱免费申请的。

存储方式:Mongodb/txt文本存储 mongodb官网可下载可视化mongodb工具

需要使用的库:

pip pymongo

pip requests

pip selenium

pip pyquery

pip requests_html

目标站点:搜狗微信文章

开始爬取:

核心代码:
WeChatSpider.py

# encoding: utf-8
'''
@author: bo

@file: WeChatSpider.py
@time: 2018/10/10/010 15:02
@desc:
'''
import json
import re
import pymongo
import requests
from selenium import webdriver
from pyquery import PyQuery as pq
from urllib.parse import urlencode
from requests_html import HTMLSession
from selenium.webdriver.chrome.options import Options
from config import *

session = HTMLSession()
headers = {
    'Cookie': 'ABTEST=0|1539091980|v1; SUID=BE9AEC782423910A000000005BBCAE0C; SUID=BE9AEC784F18910A000000005BBCAE0C; weixinIndexVisited=1; SNUID=57730592E9EF9D222DC66678EAB316BC; JSESSIONID=aaaBEIMWSxqDa_6_6gszw; SUV=00881DEF78EC9ABE5BBCAE139A438848; IPLOC=CN4401; sct=3',
    'Host': 'weixin.sogou.com',
    'Upgrade-Insecure-Requests':'1',
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
client = pymongo.MongoClient(MONGO_URL) #连接本地mongo数据库
db = client[MONGO_DB]

# 1通过关键词获取it之家的url
def get_url(keyword):
    try:
        base_url = 'https://weixin.sogou.com/weixin?'  # 微信文章链接
        data = {
            'query': keyword,
            'type': '1',
        }
        data = urlencode(data)
        url = base_url + data  # 得到一系列名为it之家的公众号的页面的url
        r = session.get(url)
        my_url = r.html.find('#sogou_vr_11002301_box_0 > div > div.txt-box > p.tit > a')  # 获取我们所需要查询的目标公众号的链接的位置
        str1 = str(my_url)
        res = re.compile('.*?href=\'(.*?)\'.*?', re.S)
        resurl = re.findall(res, str1)
        url = "".join(resurl)
        return url  # 返回it之家的url
    except:
        return None

# 2.解析页面得到页面it之家所有文章的url
def get_article_url(url):
    try:
        print('正在爬取文章信息...请耐心等待')
        options = Options()  # 使用Chrome的headless模式,可以不用启动浏览器
        options.add_argument('--headless')
        driver = webdriver.Chrome(options=options)
        # driver = webdriver.Chrome()
        driver.get(url)
        dates = []  # 日期的列表,暂时存储文章日期
        links = []  # url的列表,暂时存储文章url
        for date in driver.find_elements_by_class_name('weui_media_extra_info'):  # 获取文章的发布日期,由于文章内部的日期格式都为
            dates.append(date.text)  # 昨天,前天,三天前,诸如此类格式,所以,我选择
            # 在文章列表的外部抓取日期
        for link in driver.find_elements_by_class_name('weui_media_title'):  # 获取文章链接,这里文章链接缺少一部分
            links.append("https://mp.weixin.qq.com" + (link.get_attribute("hrefs")))  # 故使用字符串连接的方式来获取链接

        pre_links = dict(zip(links, dates))  # 把文章的链接和日期对应生成一个字典并返回
        return pre_links
    except:
        return None

# 3.得到文章的数据信息
def get_article_data(links):
    for url in links.keys():          #字典的key保存着url,url相对应的日期保存在value中
        # print(url)
        response = requests.get(url)
        article_html = response.text
        doc = pq(article_html)
        date = convert(links[url])     #将获取的日期格式化
        content = doc('.rich_media_content').text()                                       #文章内容
        total = db['ithome'].count()                                                      #当前数据库中总共数据量
        id = total+1                                                                      #id
        # precontent = content.replace('\n','')
        article_data = {
            'title': doc('#img-content .rich_media_title').text(),                        #标题
            'date': date,                                                                 #日期
            '_id': id,                                                                     #id
            'content': content,                                                            #内容
            'url': url,                                                                    # 链接
        }
        print(article_data)
        # print(article_data['title'])
        # list_title = get_mongo_titles()
        if article_data_exist(article_data):                                                   #检验数据库中是否已经存入该数据
            print('文章已存在数据库中,无需保存至数据库')                                      #存在则不需要保存至数据库
        else:                                                                                  #否则,保存到数据库内
            write_to_file(article_data)                                                        #保存到文件
            save_to_mongo(article_data)                                                        #保存到mongodb数据库

# 4.写入文件
def write_to_file(content):                                     #把获取到的每部文章的信息存入article.txt当中,一行存储一篇文章的信息
    with open('article.txt','a', encoding='utf-8') as f:
        f.write(json.dumps(content,ensure_ascii=False) + '\n')
        f.close()
# 5.保存到数据库当中
def save_to_mongo(article_data):
    try:
        if db[MONGO_TABLE].insert_one(article_data):                #插入到数据库当中
            print('成功存储到数据库')
    except Exception:
        print('存储到数据库失败',article_data)

#6.根据传入的文章信息 比较查看数据库中已经存在该文章
def article_data_exist(article_data):
    list_title = db[MONGO_TABLE].distinct('title')
    for list in list_title:
        if article_data['title'] == list:
            return True
    return False

#日期转换函数 如把2018年9月8日转换为2018-09-08
def convert(str):
    lis = re.findall('(\d+)', str)
    date = '%s-%s-%s' % (lis[0], lis[1].zfill(2), lis[2].zfill(2))
    return date

def Spider():
    url = get_url(KEYWORD)  # 获取it之家公众号的文章列表
    links = get_article_url(url)  # 得到所有文章的url
    get_article_data(links)  # 得到文章的所有信息,并且写入文件,保存到数据库

if __name__ == '__main__':
    Spider()

按时爬取:
OnTime.py

# encoding: utf-8
'''
@author: bo

@file: OnTime.py
@time: 2018/10/13/013 10:34
@desc:
'''
import datetime
import time
from WeChatSpider import *

def do_sth():
    # 把爬虫程序放在这个类里
    print(u'It is time to Spider')
    Spider()

# 让这个函数不断执行,在特定的时间内进行爬取
def one_time_run():
    while True:
        while True:
            now = datetime.datetime.now()               #获得当前的时间
            # print(now.hour, now.minute)
            #每天的10点30分 16点30分 22点30分定时爬取
            if now.hour == 10 and now.minute == 30:
                break
            if now.hour == 16 and now.minute == 30:
                break
            if now.hour == 22 and now.minute == 30:
                break
            # 每隔60秒检测一次
            time.sleep(60)
        do_sth()
        #休息一分钟后再进行爬取
        time.sleep(60)

if __name__ == '__main__':
    one_time_run()

配置文件:
congig.py

# encoding: utf-8
'''
@author: bo

@file: OnTime.py
@time: 2018/10/13/013 10:34
@desc:
'''
import datetime
import time
from WeChatSpider import *

def do_sth():
    # 把爬虫程序放在这个类里
    print(u'It is time to Spider')
    Spider()

# 让这个函数不断执行,在特定的时间内进行爬取
def one_time_run():
    while True:
        while True:
            now = datetime.datetime.now()               #获得当前的时间
            # print(now.hour, now.minute)
            #每天的10点30分 16点30分 22点30分定时爬取
            if now.hour == 10 and now.minute == 30:
                break
            if now.hour == 16 and now.minute == 30:
                break
            if now.hour == 22 and now.minute == 30:
                break
            # 每隔60秒检测一次
            time.sleep(60)
        do_sth()
        #休息一分钟后再进行爬取
        time.sleep(60)

if __name__ == '__main__':
    one_time_run()

接口:
api.py

from flask import Flask, jsonify
import pymongo
from config import *
app = Flask(__name__)

client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]

app.config['JSON_AS_ASCII'] = False   #设置ascii码为False,方便打印中文


@app.route('/',methods=['GET','POST'])
def hello_world():
    return 'please input article_list page or article_detail id or article_message title'

# 使用同一个视图函数
# <>定义路由参数 <>内需要起个名字
# 通过文章页数返回文章列表
@app.route('/article_list/<int:page>',methods = ['GET','POST'])
def get_article_list(page):
    # if request.method == 'POST':
    start = 10 * (page - 1)   # 每十条数据为一页,计算该page起点为第几条数据
    my_list = []                # 保存数据库中获得的数据
    for list in db['ithome'].find({}, {"_id:": 1, "title": 1, "date": 1}).sort('date', -1).skip(start).limit(10):
        # print(list)
        my_list.append(list)
    data = {'data': my_list}     #打包数据并返回json格式的data
    # print(data)
    return jsonify(data)

#通过文字id返回文章的信息
@app.route('/article_detail/<int:id>',methods=['GET','POST'])
def get_article_detail(id):
    data = db['ithome'].find_one({"_id":id},{"_id":0})
    # print(data)
    return jsonify(data)

#通过文章的标题返回文章的信息
@app.route('/article_message/<string:title>',methods=['GET','POST'])
def get_article_message(title):
    data = db['ithome'].find_one({"title":title})
    # print(data)
    return jsonify(data)
if __name__ == '__main__':
    app.run()

控制台执行:


1540993945.jpg

数据库存储视图:


image.png

txt文件存储:
image.png

这是自己入门python爬虫写的一篇文章,写的比较乱,如果后续有人看的话再进行修改。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容

  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,872评论 2 89
  • 一、scrapy框架介绍 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍。...
    Mr_Du_Biao阅读 350评论 0 0
  • # Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列...
    小迈克阅读 2,949评论 1 3
  • 感恩今天能够早起,老公送大宝,我就带二宝去社区体检,婆婆在家洗衣服收拾屋子,有了两个宝贝之后都要忙活起来,今天二宝...
    米朵天天阅读 155评论 0 0
  • 1我呢是在8月19这天在微信公众号看到长投理财训练营的,然后打开一看,9块钱,想着9块钱么也就是一碗米线钱,看看能...
    林梅_6895阅读 519评论 2 8