写个python,爬行【游明星空】的壁纸(3)

前文摘要/本文内容:

现在,刀已经磨成了等离子影秀了,可以上山砍柴了,从这个章节开始,写爬行脚本的内容,按照当时的设计思路,先是写爬行所有期数链接的脚本


引入第三方模块scrapy

我的爬行,很大程度都是基于scrapy的方法和内容,怎么简单怎么来,先安装scrapy模块

【pip install scrapy】




安装scrapy,总是会有一些想不到的错误让你摸不着头脑,不是每次都这么的顺利的,亲测



引入第三方模块requests

一开始我是用urllib和urllib2这两个自带库的,后面用多了requests,觉得它也挺好用的,就干脆用用用它好了,先是pip安装它

pip install requests


分析页面:

首先,我们用浏览器打开目标链接,分析一下它是怎样的一个页面

链接:http://www.gamersky.com/ent/wp/



一共有24页



点击下一页,看看url变化的规律



发现,url,竟然没有变化?!看来,是动态加载的,多半是ajax技术,F12打开调试面板,看看页面的交互情况

点击下一页,发现交互了js文件



直接访问交互js的url,看看都返回了什么玩意




从内容上分析,大概是分页栏和内容页的信息,也就是下图红框部分的内容



仔细看一下,发现每一期的链接和总页数都在里面



也就是说,只要我参数正确,直接请求它,就能得到我要的数据咯

我们看一下它ajax请求的url,是怎样的一个格式

http://db2.gamersky.com/LabelJsonpAjax.aspx?callback=jQuery183039738863782243394_1518704729182&jsondata=%7B%22type%22%3A%22updatenodelabel%22%2C%22isCache%22%3Atrue%2C%22cacheTime%22%3A60%2C%22nodeId%22%3A%2220117%22%2C%22isNodeId%22%3A%22true%22%2C%22page%22%3A1%7D

这么多的【%】号,肯定是url加密的玩意,我们先用url解码,看看它的原始数据是啥

http://db2.gamersky.com/LabelJsonpAjax.aspx?callback=jQuery183039738863782243394_1518704729182&jsondata={"type":"updatenodelabel","isCache":true,"cacheTime":60,"nodeId":"20117","isNodeId":"true","page":1}


这样就很明了了

请求的主站是:

http://db2.gamersky.com/LabelJsonpAjax.aspx


使用的是GET传参


callback回调函数,使用的函数名是:

jQuery183039738863782243394_1518704729182


传递的jsondata数据是:

{"type":"updatenodelabel","isCache":true,"cacheTime":60,"nodeId":"20117","isNodeId":"true","page":1}


从json格式来分析,应该是传递如下内容

type(类型):updatenodelabel(更新节点标签)

isCache(是否缓存):true(是)

cacheTime(缓存时间):60(60秒)

nodeId(节点ID):20117

isNodeId(是否节点Id):true(是)

page(当前页码):1(第1页)



点击下一页,发现url变化的只有page,也就是说,page的变化,决定了更新哪一个分页的数据出来,这样,url的规律就很明了了,只要把page后面的数字,对应改成2、3、4、5,一直到24,这样,所有页数的url就出来了,依次访问,就能获取到对应的数据了


提取当前列表页的内容,抓取每一期的链接url:

其实,每一页的格式都差不多那个样的,所以,我们先分析一页,以这一页为例,编写规则,去爬行其它的20多页


打开cmd,调用scrapy shell,输入第一页ajax交互的url



response响应的HTTP状态码是200,证明页面被正常打开捕捉



输入response.text,浏览页面返回的内容,发现很多这些带\u的字符,这种是unicode编码的玩意,因为cmd默认的中文编码是GBK,所以,不能显示出来,这个很好办,你只要在代码前面,加个print,就可以很友好的输出了

例如,print response.text





为了更加友好的调试,我决定用Linux的Shell来跑scrapy shell,毕竟,Win7的cmd,复制粘贴不是很好使啊



然后我们大概的看一下shell输出的内容,发现有很多诸如【\】【\r】【\n】【\t】这一类的转义字符,很明显,这些不是我们需要的东西,我们只需要里面的url链接,因此,我们必须对原始数据进行一波处理,处理方法有很多种,可以直接过滤掉这些转译字符,为了学习,我决定使用一个比较骚的操作,同时使用re模块和json模块


使用re模块提取大括号【{}】里面的内容:

所谓的re模块,是python的正则表达模块,使用的是re.findall,它会返回符合匹配规则的数列

首先,引入re模块

import re

然后,编写规则,调试输出

re.findall('\{.*?\}', response.text)



正则匹配的规则是,匹配一头一尾的大括号,由于大括号【{}】在正则表达式有特殊意义,因此需要用反斜杠【\】来转译它,【.*】代表所有字符内容,【?】代表多次匹配

然后,对应需要进行匹配的文本,于是,就输出了下图内容



这是一个数列,我们print它出来,看看是否能满足我们的要求



头部:


尾部:



这样,大括号里面的内容就提取出来了


json模块解析提取的内容:

这个很明显就是一个json格式的数据,用json来解析它,最适合不过了,先把它赋值给一个变量,我这里就赋值成content变量好了

content = re.findall('\{.*?\}', response.text)[0]

引入json模块

import json

加载解析content,并把结果赋值给data变量

data = json.loads(content)



观察json数据的结构,它是由三个key:value组成的,三个key分别是

status(状态),totalPages(总页数),body(主体内容)


json模块解析成功的数据,可以直接通过key来访问它的数据,比如,我想输出status,可以这样

print data['status']



同理,获取body里面的数据,直接data['body']


使用css选择器提取url链接:

scrapy project里面,有个LinkExtractor,它是scrapy里面一个很好用的方法,它帮助我们直接提取文本里面的url。由于我的不是scrapy project的内容,所以直接使用css选择器提取。


分析一下data['body'],发现url都在class="tit"的div里面的a标签里面,那么,我们这样提取它们出来



引入Selector

from scrapy.selector import Selector

使用css选择器,提取url,并赋值给变量links

links = Selector(text=data['body']).css('div.tit a::attr(href)').extract()


看一下提取到的url数量

len(links)


看一下url的内容

links



回到原始页面,数一下,看看一页是不是有14期,发现,数目正确,于是,想要的数据,都知道怎么拿了,是时候整合出一个python文件出来了,我希望把结果保存到一个记事本txt里面,因为这玩意又不是每天更新的,它一个星期才更新一期,所以说,txt的时效性还是蛮长的,所有代码如下:



#!usr/bin/env python
# -*- coding:utf-8 -*-


"""

=======================================
=======================================
============Author:Task138=============
===========Power By Python2============
=======================================
=======================================

"""

# Create On 2018/2/15

import re
import json
import requests
from scrapy.selector import Selector


class Get_list_url(object):
    def __init__(self):
        self.base_url = 'http://db2.gamersky.com/LabelJsonpAjax.aspx'
        self.get_data = {
            'callback': 'jQuery183039738863782243394_1518704729182',
            'jsondata': '{"type":"updatenodelabel","isCache":true,"cacheTime":60,"nodeId":"20117","isNodeId":"true","page":1}'
        }

        self.num = 1
        self.url_list = []
        self.parse(self.get_data)

        if self.url_list:
            num = 1
            total_num = len(self.url_list)
            with open('url_list.txt', 'a') as fp:
                for link in self.url_list:
                    fp.write(link + '\r\n')
                    print 'url [ %s ] write to txt success!!  [ %s / %s ]' % (link, num, total_num)
                    num += 1
                print 'program done!!'


    # 请求第一页,抓取第一页的期数url,并获取总页数,生成所有页数的url
    def parse(self, get_data):
        response = requests.get(url=self.base_url, params=get_data).text
        json_data = re.findall('\{.*?\}', response)[0]
        data = json.loads(json_data)
        total_page = data['totalPages']
        self.parse_content(data['body'], total_page)


        for page in xrange(2, int(total_page)+1):
            data = {
                'callback': 'jQuery183039738863782243394_1518704729182',
                'jsondata': '{"type":"updatenodelabel","isCache":true,"cacheTime":60,"nodeId":"20117","isNodeId":"true","page":%s}' % page
            }
            response = requests.get(url=self.base_url, params=data).text
            json_data = re.findall('\{.*?\}', response)[0]
            data = json.loads(json_data)
            self.parse_content(data['body'], total_page)

    # 解析每一页,提取每页期数的url链接
    def parse_content(self, response, total_page):
        links = Selector(text=response).css('div.tit a::attr(href)').extract()
        self.url_list += links
        if links:
            print 'links add to list success!!  [ %s / %s ]' % (self.num, total_page)
        self.num += 1

if __name__ == '__main__':
    Glu = Get_list_url()


执行效果如下图:


结尾:


说实话,这个脚本,无论是算法还是对机器的友好性,都不咋地,但是,它也就330个url,凑合一下,也OK的了


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值