段子手与神编剧共存,矫情文艺与励志故事齐飞
用户热评是网易云音乐除智能推荐外的第二法宝
语料库是所有自然语言处理模型的知识基础,甚至决定了模型的适应范围,毕竟 Garbage in, garbage out 在 NLP 领域也同样适用。常见的中文语料库包括中文维基百科、人民日报文本等,这些语料库的特点很明显:词法、语法严谨流畅,出现歧义的可能性很小。在一般的 NLP 任务中它们是非常好的选择,不过互联网上一般用户(网友)的讨论、留言,所用的词汇、语法往往并不遵循这样的特点。大量的“流行词”被赋予了全新的含义,有时候还会故意制造歧义来表达幽默、讽刺等特定意图。
选择网易云音乐的用户热评作为一种特定的网络交流环境下的语料库,除了开头提到的原因之外,还因为云村评论的点赞机制很大程度上可以作为一种筛选机制,我们可以假设,点赞数量超过 1k 的“热评”,属于被大众认可、能够引起共鸣、表意明确的内容(无论是纯粹的段子还是歌手粉丝的留言)。
网页版的网易云音乐是 Single-Page App 的典范,前端做了层层加密,要抓取它的数据并不像一般网站那么简单。不过具体的加密算法网上也有很多破解说明,毕竟只是前端加密。当然,除了前端加密,后端也设置了层层反爬虫机制。伪装 Request Headers
就不用说了,不管面对的是什么网站,这属于对后端工程师最基本的尊重^_^
。接下来就是防止爬虫 IP 被封,开始没有注意,还没有抓完全站歌手的 TOP50 热门歌曲,服务器 IP 就上了云村黑名单,并调皮地吐回错误代码:
{"code": -460, "msg": "Cheating"}
由于我们并不知道后端的反爬虫策略——实际上也不需要知道,以不变应万变,只要让爬虫的行为尽可能看起来像人类行为即可:
- 维护一个可用的代理池,每次请求随机切换代理地址;
- 一次代理请求失败,短暂的暂停一点时间再重新请求。
如果要抓取的内容不需要登录,也就是不需要考虑 IP 变化带来的 Cookie
变化,一般情况下上面两步就足够用了。以下是示例代码片段:
good_proxies = ['110.179.67.*:*',
'114.215.95.*:*',
'119.28.152.*:*',
'123.161.16.*:*',
'139.224.80.*:*',
'202.38.92.*:*',
'218.20.54.*:*',
'112.250.65.*:*',
'120.77.254.*:*',
'122.72.18.*:*',
'221.228.17.*:*',
'124.237.83.*:*',
'123.138.89.*:*',
'121.234.34.*:*',
'115.213.63.*:*',
'121.201.33.*:*']
import time
import random
import requests
class B:
proxies = good_proxies
UA = ["UA_1", "UA_2"]
def __init__(self):
self.headers = {}
self.sess = requests.session()
def _choose_randomly(self, l):
random.shuffle(l)
return l[0]
def fetch(self, url, n=10):
while n > 0:
self.headers["User-Agent"] = self._choose_randomly(self.UA)
proxy = self._choose_randomly(self.proxies)
try:
res = self.sess.GET(url,
headers = self.headers,
proxies = {"http": "http://{}".format(proxy)})
n = 0
except:
time.sleep(random.random()*3)
n -= 1
return res