整理整理之前的东西,当时有个需求要爬豆瓣短评,当时没想太多,打开Chrome,登录豆瓣,冲!!!
整一个《龙猫》 看看,豆瓣短评就在下面,点击全部
f12 看了一眼,xhr里没有,那肯定是在页面上了,果不其然,嘻嘻
data-cid 是这个评论的id,是唯一的,我们爬取评论只把 这个标签下的文本取下来就行了。
通过研究,登录之后能抓的多一点,自己的账号先登录,把cookie拿下来。
为了尽可能模拟浏览器,我用了个代理,蘑菇代理http://www.moguproxy.com/(不是打广告 - -.)
# coding : utf8
import urllib
import urllib.request
import time
import random
from bs4 import BeautifulSoup
def get_html(url,proxy):
user_agents = [
#(这里可以多填几个,你萌自己找8)
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36'
]
headers = {
"User-Agent": str(random.choice(user_agents)),
"Cookie": "chrome f12里面拿到的cookie",
'Referer': 'movie.douban.com',
'Connection': 'keep-alive'
}
http_proxy = urllib.request.ProxyHandler(proxy)
opener = urllib.request.build_opener(http_proxy)
req=urllib.request.Request(url,headers=headers)
req = opener.open(req)
html = req.read().decode('utf-8')
comment_soup = BeautifulSoup(html, 'html.parser')
comments = comment_soup.findAll('span', 'short')
page_comment = []
for comment in comments:
page_comment.append(comment.getText() + '\n')
return page_comment
def get_proxy():
for i in range(20):
print("get proxy try time:", i + 1)
proxy_url = urllib.request.urlopen(
"http://piping.mogumiao.com/proxy/api/get_ip_al?appKey=蘑菇代理的订单号&count=1&expiryDate=0&format=2&newLine=1",
).read()
proxy_origin = {"http": "http://%s" % proxy_url}
headers = {
'Accept - Encoding': 'gzip',
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"}
try:
proxy = urllib.request.ProxyHandler(proxy_origin)
opener = urllib.request.build_opener(proxy)
#因为不是所有代理都是有效可用的,拿到代理之后先去试一下,用baidu当小白鼠,可以正常访问之后,就使用这个代理,不好用就换下一个,重试20次
req = urllib.request.Request("https://www.baidu.com/", headers=headers)
req = opener.open(req)
time.sleep(0.5)
return proxy_origin
except:
continue
return None
if __name__ == "__main__":
file = open('/Users/zhangxiaoke/Desktop/comment_test.rtf', 'a', encoding='utf-8')
j = 0
for page in range(25):
proxy = get_proxy()
url = 'https://movie.douban.com/subject/1291560/comments?start=' + str(20 * page) + '&limit=20&sort=new_score&status=P'
print('爬取url :' + url + '\n')
for i in get_html(url,proxy):
file.write(i)
print(j+1, i)
j += 1
time.sleep(10)
print('end')
点击运行 :
文本里面有emogi,这个没处理,python里面好像有个 emoji包,处理表情的,有需要的pip3 install 一下,然后在文本那里处理一下
无情爬了半天,发现豆瓣只展示500条,这还是在登录的情况下,我原本以为只是页面展示500调,结果改接口参数,到500条之后就返回空了 - -
然而第二天早上醒来
忘了件事,就算我用代理 - -,就算用多个User_agent,那cookie还是我账号的 - -。。。一个账号同时在多个ip多个浏览器访问douban,douban没惯着我,直接给我封了 - -。。
这咋整,去app看看还有没有可能。
注意 :
以上代码不用代理,用自己电脑的ip和自己的cookie,也能抓,把代理那一步去掉就行。
在mac上用Charles链接iphone抓包,就是抓不到,就奇了怪了 。。 因为mac的fiddler非常难用,不是正经的开发版本,卡的1b。转战windows。这里使用 Fiddler和网易mumu模拟器。(不会Charles和fiddler的可以去看一下啊)
下载fiddler : https://pc.qq.com/detail/10/detail_3330.html
下载mumu模拟器 : http://mumu.163.com/baidu/
网上这位大佬写的非常详细,怎么使用fiddler抓包模拟器:https://blog.csdn.net/lengdaochuqiao/article/details/88170522
之后记得下载证书,要不然把代理填上之后,无法上网 - -
mumu模拟器下载完豆瓣之后打开,咱看看天空之城:
找到啦 ! (fiddler那个443没来得及处理)
https://frodo.douban.com/api/v2/movie/1291583/interests?count=30&status=done&order_by=hot&os_rom=android&apikey=0dad551ec0f84ed02907ff5c42e8ec70&channel=douban&udid=c1e35b2e04e6fadee7de08bb7c287dd46809a84b&_sig=EDicFbQBh20lHnBG2AKZr%2FUD8TM%3D&_ts=1587272260
这个链接可以改成下面这样子,就可以分页抓了,在模拟器里往下划,就会出现这个链接了,评论接口里有2个参数,可以控制返回 ’热门‘ 还是 ’最新‘ ’看过‘ 还是 ’没看过‘
#start 开始条数 count 总条数 status = done 看过 status = mark 想看 order_by = hot热评 order_by = latest最新
https://frodo.douban.com/api/v2/movie/1291583/interests?start=0&count=75011&status=done&order_by=latest&os_rom=android&apikey=0dad551ec0f84ed02907ff5c42e8ec70&channel=douban&udid=c1e35b2e04e6fadee7de08bb7c287dd46809a84b&_sig=NY106LqdT%2BysFZgXAAnvDpWuejg%3D&_ts=1587264829
注意 没有User_agent不行
只能展示 500 条,我们把start换成501试验一把:
就不显示了,这个我在本地爬了几回,然后也给我封了,可以在postman的setting里面设置一个代理,就可以继续了,
上代码了
# coding : utf8
import urllib
import urllib.request
import time
import json
def get_json(url,proxy):
headers = {
"User-Agent": 'api-client/1 com.douban.frodo/6.33.1(183) Android/23 product/cancro vendor/Netease model/MuMu rom/android network/wifi platform/AndroidPad',
'Referer': 'frodo.douban.com',
'Connection': 'keep-alive'
}
http_proxy = urllib.request.ProxyHandler(proxy)
opener = urllib.request.build_opener(http_proxy)
req = urllib.request.Request(url,headers=headers)
req = opener.open(req)
content = req.read().decode('utf-8')
jsonobj = json.loads(content)
comment_list = jsonobj['interests']
page_comments = []
for comment in comment_list:
page_comments.append(comment['comment'].strip("\n") + '\n')
return page_comments
这里我也用了代理,如果没有代理使用本机的话,可以不用,一样可以抓,但是没测试能抓多少回,我猜可能抓个10几次就403了 - - ,买了代理后把链接换成 prox_url里面就可以,或者用别人的机器和端口 ,proxy_url = {'http':u'192.xxx.xx.xx:8080'} 这样也可以
def get_proxy():
for i in range(20):
print("get proxy try time:", i + 1)
proxy_url = urllib.request.urlopen(
"http://piping.mogumiao.com/proxy/api/get_ip_al?appKey=蘑菇代理apikey&count=1&expiryDate=0&format=2&newLine=1",
).read()
proxy_origin = {"http": "http://%s" % proxy_url}
headers = {
'Accept - Encoding': 'gzip',
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"}
try:
proxy = urllib.request.ProxyHandler(proxy_origin)
opener = urllib.request.build_opener(proxy)
req = urllib.request.Request("https://www.baidu.com/", headers=headers)
#等待5秒,没有响应就跳过
req = opener.open(req,timeout=5)
time.sleep(0.5)
return proxy_origin
except:
continue
return None
if __name__ == "__main__":
# a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容
将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
file= open('/Users/zhangxiaoke/Desktop/天空之城.txt', 'a', encoding='utf-8')
j = 0
for page in range(10):
proxy = get_proxy()
# status : done 看过 mark 想看
# order_by hot 热评 latest 最新
#天空之城
url = 'https://frodo.douban.com/api/v2/movie/1291583/interests?start='+str(50 * page)+'&count=75011&status=done&order_by=latest&os_rom=android&apikey=0dad551ec0f84ed02907ff5c42e8ec70&channel=douban&udid=c1e35b2e04e6fadee7de08bb7c287dd46809a84b&_sig=NY106LqdT%2BysFZgXAAnvDpWuejg%3D&_ts=1587264829'
print('爬取'+url + '\n')
for i in get_json(url,proxy):
file.write(i)
print(j+1, i)
j += 1
time.sleep(10)
print('end')
![image.png](https://upload-images.jianshu.io/upload_images/18395572-ccb572562ef4ca42.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image.png](https://upload-images.jianshu.io/upload_images/18395572-faa34b5fba14c24e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
相比在web端抓取呢,app端不用cookie,但是最好使用代理,app端解析json,web端解析html。
生成词云
使用 jieba分词 colection统计次频率 把高频词用wordcloud做词云
from wordcloud import WordCloud
import matplotlib.pyplot as p
import jieba
import jieba.analyse
import collections
import numpy
import re
import numpy as np
def wordCloudImg(path) :
f = open(path,'r',encoding='UTF-8')
# 文本预处理
pattern = re.compile(u'\t|\n|\.|-|:|;|\)|\(|\?|"') # 定义正则表达式匹配模式
string_data = re.sub(pattern, '', f.read())
f.close()
# 将符合模式的字符去除
jieba.analyse.set_stop_words("/Users/zhangxiaoke/Desktop/stopwords.txt")
stop_list = [u'的', u',',u'和', u'是', u'随着', u'对于', u'对',u'等',u'能',u'都',u'。',u' ',u'、',u'中',u'在',u'了',
u'通常',u'如果',u'我们',u'需要',u'就是',u'他们',u'那么',u'有',u'一个',u'一部',u'这部',u'没有',u'还是',u'时候',u'看到',u'还有',u'觉得']
use_workd = ['久石让']
for uword in use_workd:
jieba.add_word(uword)
cut_text = jieba.cut(string_data,cut_all=False,HMM=True)
object_list = []
for word in cut_text:
if word not in stop_list:
if len(word) == 1:
continue
else:
object_list.append(word)
word_counts = collections.Counter(object_list)
word_count_top = word_counts.most_common(150)
new_file = open('/Users/zhangxiaoke/Desktop/final_word.txt', 'w', encoding='utf-8')
for wordd in word_count_top:
print(wordd[0]," ",wordd[1]*151)
new_file.write(wordd[0])
new_file.close()
final_file = open('/Users/zhangxiaoke/Desktop/final_word.txt', 'r', encoding='utf-8')
cut_text2 = jieba.cut(final_file.read(),cut_all=False,HMM=True)
str = ' '.join(cut_text2)
# wordcloud = WordCloud(
# font_path="/System/Library/Fonts/Supplemental/Songti.ttc",
# background_color="white",
# width=1380,
# height=880).generate(str)
x, y = np.ogrid[:600, :600]
mask = (x - 300) ** 2 + (y - 300) ** 2 > 230 ** 2
mask = 255 * mask.astype(int)
wordcloud = WordCloud(
font_path="/System/Library/Fonts/Supplemental/Songti.ttc",
background_color="white",
mask=mask).generate(str)
#图像显示 - interplotation:默认"None",可用字符串类型命令设定
p.imshow(wordcloud)
p.axis("off")
p.show()
if __name__ == "__main__":
path = '/Users/zhangxiaoke/Desktop/龙猫.txt'
wordCloudImg(path)
效果图 :
3836 < a href="javascript:;" class="j a_vote_comment" onclick="">有用 a> < a href="https://www.douban.com/people/Lan.die/" class="">Lan~die a> 看过 2007-02-10
龙猫,好烂漫的幻想。 消失的乡下风景、慈祥的爷爷奶奶、嬉笑追逐的儿时玩伴,是童年最纯真美好的回忆。