• 目录

    • 前言
    • 创建项目
    • 创建Item
    • 创建Spider
    • 解析付费榜
    • 运行爬取初始app列表
    • Selenium调用JS脚本
    • 获取app详情

前言

熟悉Scrapy之后,本篇文章带大家爬取七麦数据(https://www.qimai.cn/rank )的ios appstore付费应用排行榜前100名应用。

爬取内容包括app在列表中的下标,app图标地址,app的名称信息,app的类型,在分类中的排行,开发者,详情等。

考虑的问题:

  • Forbidden by robots.txt的错误
  • 网页返回403
  • 页面通过动态渲染,普通的请求url,在页面渲染之前已经返回response,解析没有数据
  • 列表一页20个app,想要拿到前100个需要翻页,但是翻页没有更改url,而是通过js动态加载

创建项目

在需要放置项目的目录下,

> scrapy startproject qimairank

回车即可创建默认的Scrapy项目架构。

创建Item

创建Item来存储我们爬取的app在列表中的下标,app图标地址,app的名称信息,app的类型,在分类中的排行,开发者,详情。
修改items.py,在下面增加

class RankItem(scrapy.Item):# 下标index = scrapy.Field()# 图标地址src = scrapy.Field()# app标题信息title = scrapy.Field()# app类型type = scrapy.Field()# 分类中的排行type_rank = scrapy.Field()# 开发者company = scrapy.Field()# 详情信息info = scrapy.Field()

创建Spider

spiders目录下创建RankSpider.py,并创建class RankSpider,继承于scrapy.Spider。

import scrapyclass RankSpider(scrapy.Spider):name = "RankSpider"start_urls = ["https://www.qimai.cn/rank"]def parse(self, response):pass
  • name:用于区别Spider,该名字必须是唯一的。
  • start_urls:Spider在启动时进行爬取的url列表,首先会爬取第一个。
  • def parse(self, response):得到url的response信息后的解析方法。

解析付费榜

解析用的Selectors选择器有多种方法:

  • xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表 。
  • css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表.
  • extract(): 序列化该节点为unicode字符串并返回list。
  • re(): 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。

下面我们用xpath()选择节点,xpath的语法可参考w3c的http://www.w3school.com.cn/xpath/xpath_nodes.asp 学习,需要熟悉语法、运算符、函数等。

def parse(self, response):base = response.xpath("//div[@class='ivu-row rank-all-item']/div[@class='ivu-col ivu-col-span-8'][2]//ul/li[@class='child-item']/div[@class='ivu-row']")for box in base:# 创建实例rankItem = RankItem()# 下标rankItem['index'] = \box.xpath(".//div[@class='ivu-col ivu-col-span-3 left-item']/span/text()").extract()[0]# 图标地址rankItem['src'] = box.xpath(".//img/@src").extract()[0]# app名称信息rankItem['title'] = box.xpath(".//div[@class='info-content']//a/text()").extract()[0]# app类型rankItem['type'] = box.xpath(".//div[@class='info-content']//p[@class='small-txt']/text()").extract()[0]# 分类中的排行rankItem['type_rank'] = box.xpath(".//div[@class='info-content']//p[@class='small-txt']//span[@class='rank-item']/text()").extract()[0]# 开发者rankItem['company'] = box.xpath(".//div[@class='info-content']//p[@class='small-txt']//span[@class='company-item']/text()").extract()[0]# 详情页地址infoUrl = "https://www.qimai.cn" + box.xpath(".//div[@class='info-content']//a/@href").extract()[0]yield rankItem

运行爬取初始app列表

直接运行

qimairank>scrapy crawl RankSpider -o data.json

你会发现窗口没有item输出,data.json中也没有数据,是我们写错了吗?

scrapy默认遵守robot协议的,在访问网址前会先访问robot.txt来查看自己是否有权限访问。如果网站不允许被爬,就不能访问。
怎么样不遵守协议呢?

settings.py# Obey robots.txt rules
ROBOTSTXT_OBEY = False

再次运行仍然失败,我们来看下具体原因:

因为七麦网站对请求的User-Agent做了校验,解决办法是在配置文件

settings.py# Enable or disable downloader middlewares
# See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {#    'qimairank.middlewares.QimairankDownloaderMiddleware': 543,'qimairank.middlewares.RandomUserAgent': 1,
}USER_AGENTS = ["Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)","Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)","Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)","Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)","Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)","Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6","Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1","Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0","Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5","Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20","Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
]

并在middlewares.py中创建RandomUserAgent

import randomclass RandomUserAgent(object):"""随机获取settings.py中配置的USER_AGENTS设置'User-Agent'"""def __init__(self, agents):self.agents = agents@classmethoddef from_crawler(cls, crawler):return cls(crawler.settings.getlist('USER_AGENTS'))def process_request(self, request, spider):request.headers.setdefault('User-Agent', random.choice(self.agents))

再次运行,没有报错,但是没有数据,是我们的xpath写错啦?我们在parse中增加输出body的信息

可以看到body为空,没有我们需要的列表数据,这是因为七麦数据是通过js动态渲染的,在渲染完成前,我们的response已经返回,那么怎么样才能等一等呀,等到渲染完成才返回呢?

爬取动态渲染的方式,我知道是通过Splash或者Selenium,像我们的桌面版系统可以选择用Selenium,操作可以设置可视化,所有界面操作都能看见,Splash依赖于Docker,无界面。

安装Selenium包:

pip install selenium

使用前需要安装驱动,配置详情点击

驱动安装完成,在middlewares.py中创建 SeleniumMiddleware

class SeleniumMiddleware(object):def __init__(self):self.timeout = 50# 2.Firefox---------------------------------# 实例化参数对象options = webdriver.FirefoxOptions()# 无界面# options.add_argument('--headless')# 关闭浏览器弹窗options.set_preference('dom.webnotifications.enabled', False)options.set_preference('dom.push.enabled', False)# 打开浏览器self.browser = webdriver.Firefox(firefox_options=options)# 指定浏览器窗口大小self.browser.set_window_size(1400, 700)# 设置页面加载超时时间self.browser.set_page_load_timeout(self.timeout)self.wait = WebDriverWait(self.browser, self.timeout)def process_request(self, request, spider):# 当请求的页面不是当前页面时if self.browser.current_url != request.url:# 获取页面self.browser.get(request.url)time.sleep(5)else:pass# 返回页面的responsereturn HtmlResponse(url=self.browser.current_url, body=self.browser.page_source,encoding="utf-8", request=request)def spider_closed(self):# 爬虫结束 关闭窗口self.browser.close()pass@classmethoddef from_crawler(cls, crawler):# 设置爬虫结束的回调监听s = cls()crawler.signals.connect(s.spider_closed, signal=signals.spider_closed)return s

在settins.py中配置

# Enable or disable downloader middlewares
DOWNLOADER_MIDDLEWARES = {#    'qimairank.middlewares.QimairankDownloaderMiddleware': 543,'qimairank.middlewares.RandomUserAgent': 1,'qimairank.middlewares.SeleniumMiddleware': 10,
}

再次运行scrapy crawl RankSpider -o data.json,啦啦啦~这回有数据啦。

Selenium调用JS脚本

观察爬取出来的data.json,发现怎么肥四,只有20条数据,而且除了前6个的app图标都是七麦的默认图标。

这是因为七麦数据的列表默认每页20条,而且默认渲染前6个的图标,其余的页需要触发滑动事件加载,而且滑动到的图标才开始渲染。这样怎么办呢?我们只需要滑动到可以加载的按钮就可以啦,检查发现在三个列表的外层标签有一个class为cm-explain-bottom的标签

我们用Selenium调用js脚本,滑动到这个标签就可以啦,在中间件process_request方法更改

def process_request(self, request, spider):# 当请求的页面不是当前页面时if self.browser.current_url != request.url:# 获取页面self.browser.get(request.url)time.sleep(5)# 请求的url开始为https://www.qimai.cn/rank/时,调用滑动界面,每页20个,滑动4次if request.url.startswith("https://www.qimai.cn/rank"):try:for i in (0, 1, 2, 3):self.browser.execute_script("document.getElementsByClassName('cm-explain-bottom')[0].scrollIntoView(true)")time.sleep(4)except JavascriptException as e:passexcept Exception as e:pass

再次执行scrapy crawl RankSpider -o data1.json,则可看见已经生成data1.json里面有100个item。

获取app详情

详情页需要跟进url,我们在RankSpider#parse方法中,不用yield Item,而是yield Request就可以跟进。

# 详情页地址
infoUrl = "https://www.qimai.cn" + box.xpath(".//div[@class='info-content']//a/@href").extract()[0]
# yield rankItem
yield Request(infoUrl.replace("rank", "baseinfo"), self.parseInfo,meta={'rankItem': dict(rankItem).copy()}, dont_filter=True)

解析的infoUrl替换"rank"字符串为"baseinfo"就可以访问app应用信息页,用meta传递item到下一个解析方法中,用软拷贝的方式,避免Item因为地址相同,内容覆盖。

self.parseInfo为指定这次请求的解析方法,

def parseInfo(self, response):print("基地址:" + response.url)if response.status != 200:returnrankItem = response.meta['rankItem']info = dict()base = response.xpath("//div[@id='app-container']")if base.extract():# try:# 描述try:info['desc'] = base.xpath(".//div[@class='app-header']//div[@class='app-subtitle']/text()").extract()[0]except Exception as e:print("无描述")# 开发商info['auther'] = base.xpath(".//div[@class='app-header']//div[@class='auther']//div[@class='value']/text()").extract()[0]# 分类info['classify'] = base.xpath(".//div[@class='app-header']//div[@class='genre']//div[@class='value']/a/text()").extract()[0]# appidinfo['appid'] = base.xpath(".//div[@class='app-header']//div[@class='appid']//div[@class='value']/a/text()").extract()[0]# appstore地址info['appstorelink'] = base.xpath(".//div[@class='app-header']//div[@class='appid']//div[@class='value']/a/@href").extract()[0]# 价格info['price'] = base.xpath(".//div[@class='app-header']//div[@class='price']//div[@class='value']/text()").extract()[0]# 最新版本info['version'] = base.xpath(".//div[@class='app-header']//div[@class='version']//div[@class='value']/text()").extract()[0]# 应用截图info['screenshot'] = base.xpath(".//div[@class='router-wrapper']//div[@class='app-screenshot']//div[@class='screenshot-box']//img/@src").extract()# 应用描述info['desc'] = base.xpath(".//div[@class='router-wrapper']//div[@class='app-describe']//div[@class='description']").extract()[0]# 应用基本信息info['baseinfo'] = []for infoBase in base.xpath(".//div[@class='router-wrapper']//div[@class='app-baseinfo']//ul[@class='baseinfo-list']/li"):# print(info['baseinfo'])try:info['baseinfo'].append(dict(type=infoBase.xpath(".//*[@class='type']/text()").extract()[0],info=infoBase.xpath(".//*[@class='info-txt']/text()").extract()[0]))except Exception as e:passrankItem['info'] = info# 替换图标 列表加载为默认图标rankItem['src'] = \response.xpath("//*[@id='app-side-bar']//div[@class='logo-wrap']/img/@src").extract()[0]yield rankItem

再次执行scrapy crawl RankSpider -o data1.json,则可看见已经生成data2.json,但是生成的列表不是排行的列表,甚至是乱序的,原因是因为我们使用了url跟进返回,每个页面的请求返回的速度不一样,需要排序的话就写个小脚本按照index排个序。

项目源码

原文链接

Scrapy 爬取七麦 app数据排行榜相关推荐

  1. scrapy爬取豆瓣top250电影数据

    scrapy爬取豆瓣top250电影数据 scrapy框架 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. sc ...

  2. 利用python爬取天气预报_python实现天气爬虫——利用xpath爬取七天天气预报数据...

    python实现天气爬虫--利用xpath爬取七天天气预报数据 import pandas as pd import lxml import requests import csv from lxml ...

  3. 在当当买了python怎么下载源代码-Python爬取当当网APP数据

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理 以下文章来源于AirPython ,作者星安果 目标 场景:有时候通过传统的方法去 ...

  4. Python爬取当当网APP数据

    目标 场景:有时候通过传统的方法去爬一些 Web 网页或者 APP,受限于对方的反爬方案,很难爬到想要的数据,这个时候可以考虑使用「Appium」结合「mitmproxy」的方式去爬取数据. 其中,A ...

  5. 使用Appium爬取淘宝App数据

    0x01.介绍说明 1.简介 Appium是一个自动化测试开源工具.通过WebDriver协议驱动IOS.Android.Windows Phone平台上的原生应用.混合应用和web应用. 2.App ...

  6. 简书推荐作者风云榜(爬取简书app数据)

    一.前言 自处女作<爬取张佳玮138w+知乎关注者:数据可视化>一文分布后,来简书快一个月了(20170831).但一直不怎么熟悉这个平台,因此,这回爬取简书app里的推荐作者并进行简单可 ...

  7. Scrapy爬取新浪微博用户粉丝数据

    一般来说pc端的信息是最为全面的,但是防范措施也是最严格的.所以不能走weibo.com这个域名下进行爬取,新浪微博在pc端的反扒措施较为全面.而手机端的数据则相对好爬取,而且数据都是Json格式,解 ...

  8. 使用scrapy爬取京东的手机数据

     使用scrapy爬取京东的数据 本文目的是使用scrapy爬取京东上所有的手机数据,并将数据保存到MongoDB中 一.项目介绍 主要目标 使用scrapy爬取京东上所有的手机数据 将爬取的数据存储 ...

  9. Python加密破解爬取七麦数据网APP榜单数据

    免责声明 七麦数据(原ASO100)是七麦科技推出的国内专业的移动应用数据分析平台,是国内同时打通App数据.微信公众号数据.小程序数据的数据分析平台. 软件均仅用于学习交流,请勿用于任何商业用途!感 ...

最新文章

  1. MySoft.Data入门篇:实体生成
  2. 【转载】用 Pyinstaller 来打包 + 解决打包结果过大问题
  3. android常用代码
  4. 【Redis】9.10.Redis持久化方式之RDBAOFAOF和RDB区别场景分析
  5. 设置Proxy Server和SQL Server实现数据库安全
  6. tomcat基础应用详解
  7. python编程入门第九讲,小甲鱼python视频第九讲(课后习题)
  8. Datalogic得利捷推出物流应用领域全新标杆产品——AV900
  9. 科赫小雪花python实验报告_基于python绘制科赫雪花
  10. jsp+ssm+mysql实现的校园二手市场交易平台视频教程
  11. html注册页面带验证码,登陆注册-带图片的验证码
  12. java 图片渐变消失_透明背景图像与渐变
  13. 三栏式布局详解(代码+图解)
  14. python dict key类型_Python——dict(自定义类作key)
  15. 一周信创舆情观察(1.24~2.6)
  16. 为什么软件系统开发公司不会同意技术入股
  17. PowerQuery 相对路径解决方案
  18. MySQL数据库绿色安装 mysql-5.7.31
  19. 清理 Snapd以释放磁盘空间
  20. 2022年中职——网络搭建国赛2脚本写法(超详细解析)

热门文章

  1. 约束你的git操作,让你生无可恋。
  2. 小写数字转大写 一二三...
  3. [读书笔记] 代码整洁之道(一)
  4. Kylin 4 使用和优化在有赞的实践
  5. cesium将默认底图设置为不显示
  6. 【信息系统项目管理师 - 备考宝典 - 39】历年考试试题易错点题库
  7. PC端无线连接打印机
  8. 面试管:Zookeeper在项目的典型应用场景请你回答一下
  9. 运行python代码import cv2时报错的解决方法
  10. 非正式纳新题解(C语言)