网易有道词典爬虫

起源

之前在有道词典上的"有道晨读"栏目看过一些连载的双语文章,还有真人朗读,觉得很不错,像<小王子>,<老人与海>,<追风筝的人>等.
但是专栏的文章是按时间排序的,同一部作品并不连续出现,想要看一部完整的连载作品很不方便,所以就想通过爬虫的方法把这些文章整理出来,方便查看防止丢失(有道词典上过老的文章会不会出现在列表中,只保留最新500篇)

环境

手机:Android 8.0.0
电脑:macOS 10.14.1,Charles 4.2.7,Python 3.7.0,mongoDB 4.0.0

准备工作

  1. 设置手机HTTP代理:确保移动设备与 Mac 笔记本在同一局域网内,添加代理ip地址(Mac内网地址)和端口号(8888),如图所示:


    wechatimg2
  2. 在 Mac 中打开 Charles 应用
  3. 在移动端访问接口数据,在 Charles 弹出的确认窗中选择 Allow,允许即可
  4. 这里,我们浏览有道晨读的专栏主页,在Charles中找到获取文章列表的接口:http://dict.youdao.com/infoline/style?client=mobile&apiversion=3.0&lastId=0&style=morning&order=desc&size=10&keyfrom=mdict.7.8.5.android&model=MI_5s_Plus&mid=8.0.0&imei=99000828489816&vendor=xiaomi&screen=1080x1920&ssid=kkmh-2.4&network=wifi&abtest=0.
    wechatimg1

    20190121105502

分析(踩坑)过程

这一节主要是记录一下给自己看的,嫌麻烦可直接略过,从下一节开始看

经过分析,接口中的很多参数对于我获取数据都是无用的,简化后的接口为
https://dict.youdao.com/infoline/style?style=morning&client=mobile&lastId=0&size=10
这是一个分页查询的接口,style和client是不变的,lastId表示id的最大值,size即每页大小,默认10.如此,把每次返回文章列表(id从大到小排序)的最后一篇文章的id作为下一次请求的参数,即可遍历全部文章,代码如下

import urllib.request
import json

def get_cards(last_id=0, size='10'):
    url = cardsUrl
    if last_id is not None:
        url = url + '&lastId=' + last_id
    if size is not None:
        url = url + '&size=' + size
    response = urllib.request.urlopen(url)
    result = response.read().decode('utf-8')

    card_list = json.loads(result)['cards']
    if len(card_list) > 0:
        last_id = card_list[-1]['id']
    return card_list, last_id

def save_articles():
    global cards
    card_list, lastId = get_cards(None, '10')
    cards = cards + card_list
    # insert_into_mysql(cards)
    while len(card_list) > 0:
        card_list, lastId = get_cards(lastId, '10')
        cards = cards + card_list
    print('文章列表下载完成,共%d篇文章' % (len(cards)))
    insert_into_mysql()

其实用这种方法只能获取到"有道晨读"栏目的最新500篇文章,再旧点的文章通过这个接口就获取不到了.不过,通过在浏览器中查看文章的详情页,找到了一个根据文章的pid(有道词典的文章编号)获取文章详情的接口:http://xue.youdao.com/sw/m/1417209?showmethod=native .返回结果里有一个related字段,就是页面上的相关阅读,是不是可以通过递归的访问文章的related就可以遍历所有的文章?试了一下,结果发现只有一部分文章会出现在related里,有一些永远不会出现,而且最新的文章都不出现的related里的.

20190121142930

不过,我发现这个接口里的文章pid都是数字,我只要不停改变这个数字应该就能获取所有文章了.而且小于1000000的pid是没有文章的,在当时(2018-12-13)最新的文章pid在16000001700000.所以我先爬取10000001600000的旧数据,再以后每次想更新文章库的时候可以根据已经爬取的最大pid来爬取新的数据.
我一开始是用的MySQL来存储爬取到的文章,但是后来发现文章的字段格式不太规范,总是出现空字段或者字符串过长等问题,写了好多控制判断之类的,好麻烦,后来索性用MongoDB来存储,方便了很多,直接插入一个json就行了.

正式开始

首先,创建MongoDB库,并把pid设为唯一索引,使用pymongo获取数据库连接

import pymongo

client = pymongo.MongoClient()
db = client['dish']
collection = db['youdao_dict']

根据pid获取文章信息

articleUrl_suffix = '?showmethod=native&keyfrom=wap&client=wap'
articleUrl_prefix = 'http://xue.youdao.com/sw/m/'

def crawler_by_pid(pid):
    try:
        response = urllib.request.urlopen(articleUrl_prefix + str(pid) + articleUrl_suffix)
        result = response.read().decode('utf-8')
        article = json.loads(result)
        if article is None:
            return {}
        return article
    except:
        return crawler_by_pid(pid)

插入文章

def insert_article(article):
    try:
        collection.insert_one(article).inserted_id
    except pymongo.errors.DuplicateKeyError:
        pass

一开始文章很多,可以开启多线程分别爬取,完整代码可以参考这里

成果

截止到2019-01-21更新,已经爬了30多万篇文章,而且信息很详细,包含文章内容(html格式),栏目,标签,音视频链接(如果有)等.


20190121152842

20190121152831

查一下<小王子>连载的文章,看了一下还不错.

20190121154107

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

推荐阅读更多精彩内容