猫眼电影—流浪地球爬虫(1)

再来一波流浪地球的爬虫,不过这次爬的是猫眼电影。而且这次不再是用scrapy而是用最常规的方法requests
同时这里还要详细讲几个别的问题。

  • 什么是Ajax
  • 如何进行反爬
  • 如何储存到MongoDB中

首先,常规操作进行猫眼电影的网址进行分析。但是我们发现在其网页端,它的评论往往没有那么多。
此时我们用的是猫眼电影的手机端url:http://m.maoyan.com/movie/248906/morecomments?_v_=yes

猫眼页面.png

大家可以往下滑,发现在页面没有跳转的情况下,内容就加载出来了,可以知道这里用的是Ajax加载的方式。
那么什么是Ajax呢?

Ajax

Ajax,全称为Asynchronous JavaScript and XML,即异步的JavaScript和XML。它不是一门编程语言,而是利用JavaScript在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。

对于传统的网页,如果想更新其内容,那么必须要刷新整个页面,但有了Ajax,便可以在页面不被全部刷新的情况下更新其内容。在这个过程中,页面实际上是在后台与服务器进行了数据交互,获取到数据之后,再利用JavaScript改变网页,这样网页内容就会更新了。

Ajax实现原理

Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。
具体大家可以自行Google哦。

Ajax分析方法

那么我们在刷新,获取信息的时候,我们看到的url是没有变化的,而是一次次的Ajax请求渲染了网页。那么我们应该去哪里查看呢?
当然是右键——检查,借助开发者工具进行检查。

检查.png

不过这一次我们关注的就不是Elements选项卡了,而是Network选项卡。
我们进行切换并且刷新,就能获得如图所示的信息:

Network.png

那么在这里:


XHR.png

选择XHR,筛选出来的就是Ajax请求啦。
我们选择开头有comments.json的条目,在它的Request Headers可以看到比传统的请求头中多了一项X-Requested-With: superagent,而superagent是一种轻量级的Ajax请求方式。

随后,我们点击Preview选项卡,可以看到网页是json格式,而chrome已经帮我们解析出来了

json.png

可以看到在data下,有我们需要的东西。
此时,想要获取这些内容非常容易了,就像是获取字典的值一样。

res = requests.get(url,timeout,headers=self.headers)
comments = res.json()['data']['comments']

这样我们就能获取评论数据,进行下一步提取了。

同时我们在Headers里可以看到真实的url:http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset=0&limit=15&ts=0&level=2&type=3,并且请求方式是get
那么我们多点击几个,观察url就会发现,其中变化的只有参数offset,并且是每15进行累加。

代码

直接上代码吧。

import requests
import time
from datetime import datetime
from pymongo import MongoClient
from lxml import etree
import random


class maoyan():
    def __init__(self):
        self.headers = {
                'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36                       (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
                'cookie':"_lxsdk_cuid=163f4936fa628-0651e9953b7cba-791238-144000-163f4936fa7c8; v=3; iuuid=A83BE960AA7E11E8B6349B995F5768EC558368427A114227869310FFD50B50A1; webp=true; ci=185%2C%E5%98%89%E5%85%B4; _lx_utm=utm_source%3Dgoogle%26utm_medium%3Dorganic; _lxsdk=438345E032A511E9BDC5F9F05A760829F59E3BE1237E422D9B95E24FCA63731A; __mta=254523319.1528816694943.1535432227454.1550402539437.7; _lxsdk_s=168fb2aa1e2-1c1-2d8-2a8%7C%7C24",
                }
    #反爬
    def get_comments(self,i,timeout,proxy=None):
        page = i*15
        num_retries = 6
        url = 'http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset={}&lim                 it=15&ts=1550476464599&level=2&type=3'.format(page)
        
        if proxy == None:
            try:
                res = requests.get(url,timeout,headers=self.headers)
                
            except:
                if num_retries>0:
                    time.sleep(10)
                    print('网页获取出错,10s后将获取倒数第{}次'.format(num_retries))
                    res= requests.get(url,timeout,headers=self.headers)
                    num_retries -= 1
                    
                else:
                    print('开始使用代理')
                    time.sleep(10)
                    proxy = self.get_ip
                    res = requests.get(url,timeout,proxies=proxy,headers=self.headers)
                    
        else:
            try:
                proxy = self.get_ip
                res = requests.get(url,timeout,proxies=proxy,headers=self.headers)
                
            except:
                if num_retries > 0:
                    time.sleep(10)
                    proxy = self.get_ip
                    res = requests.get(url,timeout,proxies=proxy,headers=self.headers)
                else:
                    print('代理失败,取消代理')
                    res = requests.get(url,timeout,headers=self.headers)

        
        comments = res.json()['data']['comments']
        return comments
    #保存到MongoDB中
     def save_data(self,comment):
        client = MongoClient()
        db = client['maoyan']
        collection = db['lldq']
        try:
            if collection.insert_one(comment):
                print('Saved to Mongo')
        except:
            print('无法保存')
    #获取代理       
    def get_ip(self):
        url = 'http://www.xiladaili.com/http/'
        response = requests.get(url)
        t = response.text
        html = etree.HTML(t)
        result = html.xpath("//table[@class='fl-table']/tbody/tr[{}]/td[1]/text()".format(random.randint(1,50)))
        proxy = {
                'https':str(result[0])
                }
        return proxy

if __name__ == '__main__':
    for i in range(0,500):
        if i%5 == 0:
            time.sleep(1)
            my = maoyan()
            d = my.get_comments(i,timeout=3)
            my.parse_comments(d,i)
        
    
            
        

反爬

我在get_comments()函数里写了一大段,其实是为了更好的反爬。
首先就是请求头,写上了heasersuser-agentcookie,这是为了让网站认为这是一个人发送的请求,而不是机器。
其次,这里多加了一个代理proxies

def get_ip(self):
        url = 'http://www.xiladaili.com/http/'
        response = requests.get(url)
        
        t = response.text
        html = etree.HTML(t)
        result = html.xpath("//table[@class='fl-table']/tbody/tr[{}]/td[1]/text()".format(random.randint(1,50)))
        proxy = {
                'https':str(result[0])
                }
        return proxy

代理是通过一个免费网站中获得的,随机取得一个ip,用于requests
虽然代码很长,但是简单,就是有点繁琐。
同时在请求一个url后,经常会time.sleep(),否则,请求的太过于频繁,就会被封的。
最后requests.get中的timeout参数可以设定等待连接的秒数,超过时间,就会抛出异常。

储存

这一次,我们将数据存入MongoDB

准备工作

具体自行搜索啦,怎么安装,下载。

连接MongoDB

连接MongoDB时,我们需要使用的是,PyMongo库里面的MongoClient。一般来说,传入MongoDB的ip和端口即可。

import pymongo import MongoClient

client = pymongo.MongoClient(host='localhost',port=27017)

这样就可以创建MoongoDB的连接对象啦。
当然我们也可以换种方式:

client = MongoClient('mongodb://localhost:27017/')

指定数据库

MongoDB中可以建立多个数据库,接下来我们需要指定操作哪个数据库,在这里,我们以建立maoyan为例:

db = client['maoyan']

或者

db = client.maoyan

指定集合

在每个数据库里又有许多集合(collection),它们类似于关系型数据库中的表。

下一步就是要指定操作的集合,同样我们建立名为lldq的集合:

collection = db['lldq']

或者

collection = db.lldq

插入数据

此时,我们可以插入数据了。
一般数据以字典的形式表示,比如我们如果要获取我们想要的id,性别,评论,分数,等等:

comment = {'content': com['content'], 'gender': com['gender'],
'id': com['id'],
'nick': com['nick'],
'replyCount': com['replyCount'], 
'score': com['score'],
'time': com['time'], 
'upCount': com['upCount'],
'userId': com['userId'], 
'userLevel': com['userLevel']
}

诸如这种形式。
我们可以使用insert_one()insert_many()方法来插入单条和多条记录

collection.insert_one(comment)

如果你是用的是insert_many(),就要将数据以列表的形式传递。
比如,你有两个字典,分别为dic1,dic2,要存储到mongodb

collection.insert_many([dic1,dic2])

可视化工具

最后储存了一大堆,可是怎么看呢?
这里推荐Robo 3T,官方网站,三大平台都支持,下载链接
另外,还有一个简单易用的可视化工具——Studio 3T,它同样具有方便的图形化管理界面,官方网站,同样支持三大平台,下载链接

预告

接下俩,会讲讲,可视化函数,以及对这次爬取到的数据的处理。
最后请大家批评指正!

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

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,456评论 1 45
  • 前端开发面试知识点大纲: HTML&CSS: 对Web标准的理解、浏览器内核差异、兼容性、hack、CSS基本功:...
    秀才JaneBook阅读 2,344评论 0 25
  • HTTP基本原理 URI、URL、URN(Uninform Resource) URI(Identifier):统...
    GHope阅读 2,073评论 2 26
  • 面试题一:https://github.com/jimuyouyou/node-interview-questio...
    R_X阅读 1,615评论 0 5
  • 前端开发知识点 HTML&CSS对Web标准的理解、浏览器内核差异、兼容性、hack、CSS基本功:布局、盒子模型...
    Hebborn_hb阅读 843评论 0 1