一, 介绍
朋友暑假实践需要美团外卖 App 评论这一份数据, 一开始我想, 这不就抓取网页源代码再从中提取数据就可以了吗, 结果发现事实并非如此, 情况和之前崔大讲过的分析 Ajax 来抓取今日头条街拍美图类似, 都是通过异步加载的方式传输数据, 不同的是这次的是通过 JS 传输, 其他的基本思路基本一致, 希望那些数据能帮到她吧
二, 流程
目标站点分析
用浏览器打开美团外卖 App 评论, F12
1. 首先我们要找到我们想要的评论数据, 在第一次 "失败" 的直接抓取网页源代码后, 我们发现它是通过 Ajax 加载的, 我们点击 JS 选项, 可以发现 JS 项目里面的返回结果有我们想要的数据, 勾选 Preserve log, 当点击查看更多评论时, 后台 (JS 里) 会出现新的 Ajax 请求, 发现还有参数 start 和的变化, 其他请求参数不变, start 的参数变化是以 10 递增的, 的参数变化可就让人摸不着头脑(这个时候我们也不要方, 因为大多情况下没有规律的参数都是没用的)
Python 资源共享群: 484031800
2. 经过我们对 http://comment.mobilem.360.cn/comment/getComments?callback=jQuery17203361018749253357_1503362214558&baike=美团外卖+Android_com.sankuai.meituan.takeoutnew&c=message&a=getmessage&start=0&count=10&_=1503362215647
进行分析后发现它的标准式为
'http://comment.mobilem.360.cn/comment/getComments?&baike=美团外卖+Android_com.sankuai.meituan.takeoutnew&start='+str(i*10),i 每次增加 1, 就包含新的十条评论的内容, 所以我们通过改变 i 的值就可以拿到不同的数据
分析 url 的网页源代码, 在源代码里有我们想要的评论数据, 我们可以用正则 (在这里正则还是比较好用的) 把我们想要的信息弄下来
开启循环, 批量抓取
保存数据至文本和数据库
# 之前是这样处理的: def parse_one_page(html): pattern2 = re.compile('"m_type":"0",(.*?),"username"', re.S) items=re.findall(pattern2,HTML) for item in items: item = "{" + item + "}" item=JSON.loads(item) write_to_file(item) print(item) save_to_mongo(item) #皮皮哥告诉了我他的独家正则匹配方法可以匹配出来, 这样的确获得的 item 没有编码问题 def parse_one_page(HTML): pattern = '\"content\":\".*?"'items=re.findall(pattern,HTML) for item in items: item =eval(item.split(':',1)[1]) write_to_file(item) print(item) save_to_mongo(item) #对一般正则写法获得的 item 进行的方法, 这是从皮皮哥那里得知的, 亲测有效 def parse_one_page(HTML): pattern = re.compile('rsion_name".*?"content":(.*?),"username"', re.S) items=re.findall(pattern,HTML) #print(items) for item in items: item = item.encode('utf-8').decode('unicode_escape') write_to_file(item) print(item) save_to_mongo(item)
三, 代码
- #config.py MONGO_URL='localhost' MONGO_DB='meituan' MONGO_TABLE='meituan'
- import requests from requests.exceptions import RequestException import JSON import re from day31.config import * import pymongo client=pymongo.MongoClient(MONGO_URL) db=client[MONGO_DB] base_url='http://comment.mobilem.360.cn/comment/getComments?callback=jQuery17209056727722758744_1502991196139&baike=美团外卖+Android_com.sankuai.meituan.takeoutnew&start=' def the_url(url): try: response = requests.get(url) if response.status_code==200: response.encoding='utf-8' return response.text return None except RequestException: print('请求出错') return None def the_total(): HTML=the_url(base_url) pattern1 = re.compile('"total":(.*?),"messages"', re.S) Total = re.findall(pattern1, HTML) Total=int(':'.join(Total)) #print(type(Total)) show='总计评论 %d 条'%Total print(show) write_to_file(show) return Total def parse_one_page(HTML): pattern2 = re.compile('"m_type":"0",(.*?),"username"', re.S) items=re.findall(pattern2,HTML) for item in items: item = "{" + item + "}" item=JSON.loads(item) write_to_file(item) print(item) save_to_mongo(item) def save_to_mongo(result): try: if db[MONGO_TABLE].insert(result): print('储存到 MongoDB 成功',result) except Exception: print('储存到 MongoDB 失败',result) def write_to_file(content): with open('meituan_result.text','a',encoding='utf-8') as f: f.write(JSON.dumps(content,ensure_ascii=False)+'\n') f.close() def main(): Total=the_total() Total=int(Total/10)+2 for i in range(Total): url = base_url + str(i*10) if the_url(url)!=None: HTML=the_url(url) parse_one_page(HTML) else: print('输完啦') ps='PS: 因为有些评论空, 所以实际评论比抓取的少' #这是我瞎猜的 write_to_file(ps) print(ps) if __name__ == '__main__': main()
四, 最后得到的数据视图和文件
五, 总结
1. 程序报错很正常, 不要一报错就问别人, 先自己思考, 百度
2. 在数据类型处理方面的知识还要加强
来源: http://www.jianshu.com/p/a9b696bd6019