豆瓣的影评爬取

豆瓣的影评爬取

相比较于上一篇新闻类数据的爬取,这篇文章多了一些关于登录账号的处理

有时登陆网站需要进行头部伪装, 比如增加头部, 还有模拟服务器登陆
* header: 我们可以加一个header(一些反爬虫的机制),设置置代理,有些网站是反爬虫,所以要将其伪装成浏览器
* Format:是登录的账号和密码以及登录失败是重定向的网址,需要注意的是登录账号和密码的

step1:我们先看一下豆瓣登录时候账号和尼玛的格式
通过豆瓣的登录界面

Hint:通过Google Chrome浏览器的右键”检查”,找到Network->Form Data找到登录账号和密码的格式,不同的网站登录的format可能会不一样。

这里写图片描述
先新建一个scrapy的project,然后再douban_book.py中编写主要的code

下面是添加header和formdata

class MailSpider(scrapy.Spider):
    name = 'douban_comment'
    allowed_domains=['account.douban.com','douban.com']
    stat_urls=['https://www.douban.com/']
    #headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0',
    headers={
             'Accept': 'application/json, text/javascript, */*; q=0.01',
             'Accept-Encoding':'gzip, deflate, sdch, br',
             'Accept-Language': 'en-US,en;q=0.8',
             'Accept-Charset':'utf-8',
             'Host':'accounts.douban.com',
             'Cache-Control': 'max-age=0',
             'Connection': 'keep-alive',
             'User-Agent':f.user_agent()}

    formdata={
        'form_email':'284600723@qq.com',
        'form_password':'284600723ganlu',
        'login':'登录',
        'redir':'https://www.douban.com/',
        'source':'None'
    }
 重写了爬虫类的方法, 实现了自定义请求, 运行成功后会调用callback回调函数
def start_requests(self):
    return [scrapy.Request(url='https://accounts.douban.com/login',
                           headers=self.headers,
                           meta={'cookiejar':1},
                           callback=self.parse_login)]

大部分登录的时候需要输入验证码,本文就采用比较暴力的解法,获取验证码的image,然后手动输入验证码进行验证

使用FormRequest.from_response()方法模拟用户登录:

通常网站通过 实现对某些表单字段(如数据或是登录界面中的认证令牌等)的预填充
使用Scrapy抓取网页时,如果想要预填充或重写像用户名、用户密码这些表单字段, 可以使用 FormRequest.from_response() 方法实现。

Cookie的保存

为了能使用同一个状态持续的爬取网站, 就需要保存cookie, 使用cookie保存状态, Scrapy提供了cookie处理的中间件, 可以直接拿来使用。
通过CookiesMiddleware

def parse_login(self,response):
    #如果需要验证码需要人为处理
    s = "captcha_image"
    s=bytes(s, encoding = "utf8")
    if s in response.body:
        link=response.xpath('//*[@id="captcha_image"]/@src').extract()[0]
        captcha_solution=input('captcha_solution:')
        captcha_id=urllib.parse.parse_qs(urllib.parse.urlparse(link).query,True)['id']
        self.formdata['captcha_solution']=captcha_solution
        self.formdata['captcha_id']=captcha_id
    # 登陆成功后, 会调用after_login回调函数
    return [scrapy.FormRequest.from_response(response,
                                             formdata=self.formdata,
                                             headers=self.headers,
                                             meta={'cookiejar':response.meta['cookiejar']},
                                             callback=self.afterlogin
                                             )]

在登录豆瓣之后,需要做两件事:
* 1,在这个页面获取对应的评论的URL。
* 2,获取下一页。

Hint:解析下一页的时候需要再scrapy.Request的一个参数”don’t_filter=True”加上这个去重的操作。

def afterlogin(self,response):
    print('afterlogin: response.url',response.url)
    self.headers['Host']='www.douban.com'
    #同一个页面解析了两次
    #每个详细的影评的url 拿出来
    url='https://movie.douban.com/review/best/'
    yield scrapy.Request(url=url,
                          meta={'cookiejar':response.meta['cookiejar']},
                          headers=self.headers,
                          callback=self.parse_comment_url
                         )
    yield scrapy.Request(url=url,
                          meta={'cookiejar':response.meta['cookiejar']},
                          headers=self.headers,
                          callback=self.parse_next_page,
                         dont_filter=True #加上这个第二次才会生效,默认去重的操作,  加上之后不去重
                         )

解析出下一页

def parse_next_page(self,response):
    print(response.status)
    try:
        next_url=response.urljoin(response.xpath('//span[@class="next"]/a/@herf')).extract()[0]
        yield scrapy.Request(url=next_url,
                          meta={'cookiejar':response.meta['cookiejar']},
                          headers=self.headers,
                          callback=self.parse_comment_url,
                          dont_filter=True
                         )

        yield scrapy.Request(url=next_url,
                          meta={'cookiejar':response.meta['cookiejar']},
                          headers=self.headers,
                          callback=self.parse_next_page,
                          dont_filter=True #加上这个第二次才会生效,默认去重的操作,  加上之后不去重
                         )
    except:
        print('next page error')
        return

下面就网页的内容分别提取出评论的链接和解析评论中有用的内容。

def parse_comment_url(self,response):
    for item in response.xpath('//div[@class="main review-item"]'):#定位一个相同的节点后,会自动寻找
        comment_url=item.xpath('div[@class="main-bd"]/h2/a/@href').extract()[0]
        comment_title=item.xpath('div[@class="main-bd"]/h2/a/text()').extract()[0]
        yield scrapy.Request(url=comment_url,
                          meta={'cookiejar':response.meta['cookiejar']},
                          headers=self.headers,
                          callback=self.parse_comment,
                          dont_filter=True
                             )
def parse_next_page(self,response):
    print('parse_next_page response.status :',response.url)
    try:
        next_url='https://movie.douban.com'+str(response.xpath('//div[@class="paginator"]/span[@class="next"]/a/@href').extract()[0])
        yield scrapy.Request(url=next_url,
                          meta={'cookiejar':response.meta['cookiejar']},
                          headers=self.headers,
                          callback=self.parse_comment_url,
                          dont_filter=True
                         )

        yield scrapy.Request(url=next_url,
                          meta={'cookiejar':response.meta['cookiejar']},
                          headers=self.headers,
                          callback=self.parse_next_page,
                          dont_filter=True #加上这个第二次才会生效,默认去重的操作,  加上之后不去重
                         )
    except:
        print('next page error')
        return
def parse_comment(self,response):
    comment=DoubanMovieCommentItem()
    comment['useful_num']=response.xpath('//div[@class="main-panel-useful"]/button[1]').extract()[0]
    comment['no_help_num']=response.xpath('//div[@class="main-panel-useful"]/button[2]').extract()[0]
    comment['comment'] = response.xpath('//div[@id="link-report"]/div/text()').extract()
    comment['title'] = response.xpath('//div[@class="article"]/h1/span[@property="v:summary"]/text()').extract()[0]
    comment['comment_page_url'] = response.xpath('//div[@id="link-report"]/div/@data-url').extract()[0]
    yield  comment

在items.py中

class DoubanMovieCommentItem(scrapy.Item):
    useful_num=scrapy.Field()                      #域和值
    no_help_num=scrapy.Field()
    people=scrapy.Field()
    people_url=scrapy.Field()
    start=scrapy.Field()
    comment=scrapy.Field()
    title=scrapy.Field()
    comment_page_url=scrapy.Field()

在piplines.py中

class DoubanMovieCommentPipeline(object):
    def process_item(self, item, spider):
        return item

在settings.py中,需要配置 一次跑一个爬虫的话,需要指定用哪个pipeline

ITEM_PIPELINES = {
    #'douban_book.pipelines.DoubanBookPipeline': 300,
    'douban_book.pipelines.DoubanMovieCommentPipeline': 900,
}

response的状态
200
https://blog.csdn.net/GarfieldEr007/article/details/77984065

在根目录下新建一个begin.py作为执行scrapy的文件
from scrapy import cmdline
cmdline.execute("scrapy crawl douban_comment -o comment.csv".split())

1xx:指示信息–表示请求已接收,继续处理
2xx:成功–表示请求已被成功接收、理解、接受
3xx:重定向–信息不完整需要进一步补充
4xx:客户端错误–请求有语法错误或请求无法实现
5xx:服务器端错误–服务器未能实现合法的请求

常见http响应状态码:
请求收到,继续处理:
100 客户端必须继续发出请求
101 客户端要求服务器根据请求转换HTTP协议版本

 操作成功收到,分析,接受:
        200      交易成功
        201      提示知道新文件的URL
        202      接受和处理、但处理未完成
        203      返回信息不确定或不完整
        204      请求收到,但返回信息为空
        205      服务器完成了请求,用户代理必须复位当前已经浏览过的文件
        206      服务器已经完成了部分用户的GET请求

 重定向:
        300      请求的资源可在多处得到
        301      永久重定向,在Location响应首部的值仍为当前URL(隐式重定向)
        302      临时重定向,在Location响应首部的值仍为新的URL(显示重定向)
        303      建议客户端访问其他URL或访问方式
        304      Not Modified 请求的资源没有改变 可以继续使用缓存
        305      请求的资源必须从服务器指定的地址得到
        306      前一版本HTTP中使用的代码,现行版本中不再使用
        307      声明请求的资源临时性删除

 客户端错误:
        400      错误请求,如语法错误
        401      未授权
           HTTP 401.1    未授权,登录失败
           HTTP 401.2    未授权,服务器配置问题导致登录失败
           HTTP 401.3    ACL  禁止访问资源
           HTTP 401.4    未授权  授权被筛选器拒绝
           HTTP 401.5    未授权  ISAPI或CGI授权失败
        402      保留有效ChargeTo头响应
        403      禁止访问
           HTTP 403.1    禁止访问  禁止可执行访问
           HTTP 403.2    禁止访问  禁止读访问
           HTTP 403.3    禁止访问  禁止写访问
           HTTP 403.4    禁止访问  要求SSL
           HTTP 403.5    禁止访问  要求SSL 128
           HTTP 403.6    禁止访问  IP地址被拒绝
           HTTP 403.7    禁止访问  要求客户端证书
           HTTP 403.8    禁止访问  禁止站点访问
           HTTP 403.9    禁止访问  连接的用户过多
           HTTP 403.10   禁止访问  配置无效
           HTTP 403.11   禁止访问  密码更改
           HTTP 403.12   禁止访问  映射器拒绝访问
           HTTP 403.13   禁止访问  客户端证书已被吊销
           HTTP 403.15   禁止访问  客户端访问许可过多
           HTTP 403.16   禁止访问  客户端证书不可信或者无效
           HTTP 403.17   禁止访问  客户端证书已经到期或者尚未生效
        404       没有发现文件、查询或URL
        405       用户在Request-Line字段定义的方法不允许
        406       根据用户发送的Accept拖,请求资源不可访问
        407       类似401,用户必须首先在代理服务器上得到授权
        408       客户端没有在用户指定的饿时间内完成请求
        409       对当前资源状态,请求不能完成
        410       服务器上不再有此资源且无进一步的参考地址
        411       服务器拒绝用户定义的Content-Length属性请求   
        412       一个或多个请求头字段在当前请求中错误
        413       请求的资源大于服务器允许的大小
        414       请求的资源URL长于服务器允许的长度
        415       请求资源不支持请求项目格式
        416       请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,       请求也不包含If-Range请求头字段
        417       服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求长
 服务器端错误: 
        500 - 内部服务器错误
           HTTP 500.100 - 内部服务器错误 
           HTTP 500-11 服务器关闭
           HTTP 500-12 应用程序重新启动
           HTTP 500-13 - 服务器太忙
           HTTP 500-14 - 应用程序无效
           HTTP 500-15 - 不允许请求 
        501 - 未实现
        502 - 网关错误
        503 - 服务不可用
        504 - 网关超时

nodename Xpath解析文本,选取此节点的所有子节点。
* / 从根节点选取。
* // 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
* . 选取当前节点。
* .. 选取当前节点的父节点。
* @ 选取属性。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值