[Python程序设计] 用Scrapy爬取学堂在线计算机类课程页面的信息
爬虫仅供学习交流使用,请勿用于商业用途,请勿高频爬取数据。由使用爬虫产生的纠纷笔者概不负责。
实验报告原文节选
2.2 遇到障碍:JS动态渲染页面
编写
spider.py
时遇到了诡异的问题,xpath
可以找到符合//*[@id = 'app']
的一个标签,但是其是空的,内部没有任何内容。打印
response.text
,格式化html
,得到的内容如下<!DOCTYPE html> <html>.....<body ondragstart="return!1"><div id="app"></div><script>var hostName = window.location.hostname,_mtac = {performanceMonitor: 1,senseQuery: 1}; !function() {var e = document.createElement("script");e.src = "//pingjs.qq.com/h5/stats.js?v2.0.4",e.setAttribute("name", "MTAH5"),-1 != hostName.indexOf("jsmh.xuetangx.com") || -1 != hostName.indexOf("www.bnuonline.com") ? e.setAttribute("sid", "500693653") : (e.setAttribute("sid", "500676615"), e.setAttribute("cid", "500679396"));var t = document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e, t)} ()</script><script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js" type="text/javascript"></script><script src="https://static-cdn.xuetangx.com/xtassets/manifest_646ae91479d55300357f.js"></script><script src="https://static-cdn.xuetangx.com/xtassets/0_745d5dea18d788f581ff.js"></script><script src="https://static-cdn.xuetangx.com/xtassets/9_d2c68e421b465c25f7dd.js"></script><script src="https://static-cdn.xuetangx.com/xtassets/119_e4a23c8e374222e46249.js"></script></body></html>
- 页面内并没有任何可以用的信息,信息是在页面加载后,由下面的
javascript
脚本向服务器获取信息,然后再转化为HTML
语句插入到网页中的。而默认的scrapy
并不支持运行javascript
脚本。 - 解决方案有两个
- 让
scrapy
获得javascript
脚本执行完后的网页。可以通过配合selenium
或者其他工具完成,但是比较麻烦。 - 找出
javascript
脚本使用的数据接口。绕过网页,直接获取数据。
- 让
- 页面内并没有任何可以用的信息,信息是在页面加载后,由下面的
2.3 分析出数据接口
可以去读
javascript
脚本,但是这样比较费事费力。我们考虑,页面上的数据每次加载肯定要从服务器动态获取,因为这些内容是要动态刷新的,没人想看到过时的课程数据。但是对于页面上的静态资源,比较图片,则不需要反复加载。通过分析加载页面时动态加载的内容,我们可以找到课程数据的实际来源。而且课程内容这么多,数据量应该不小。
使用
Chromium
内核的浏览器(或者使用Fiddler
抓包),打开该页面,进入开发者控制台,选择Network,刷按F5新,观察元素的加载。加载完毕后,让元素按从大到小排序。如果是之前的访问已经加载过的静态内容,size
会显示from memory/disk cache
,显示实际大小的就是动态加载内容。选择有实际大小并且最大的内容,一个叫?page=1
的项目显得十分可疑,单击打开,发现其是一个json
。选择preview选项卡,预览其中的内容,果然是课程信息。
现在尝试在爬虫中重现浏览器的操作。在Headers中找到了Request URL为
https://www.xuetangx.com/api/v1/lms/get_product_list/?page=1
post的数据(位于最下面的Request Payload)中为
{"query":"","chief_org":[],"classify":["1"],"selling_type":[],"status":[],"appid":10000}
在爬虫中重现(这里使用
requests
,也可以用curl
或者wget
)import requests as r url = 'https://www.xuetangx.com/api/v1/lms/get_product_list/?page=1' data = {"query":"","chief_org":[],"classify":["1"],"selling_type":[],"status":[],"appid":10000} r0 = r.post(url, data=data) print(r0.text)
发现获取的信息是空的
{"msg": "", "data": {"count": 0, "product_list": []}, "success": true}
考虑把Headers也加上。将
Requets Headers
的内容写成Python字典的形式这里推荐使用Convert cURL command syntax to Python requests, Ansible URI, browser fetch, MATLAB, Node.js, R, PHP, Strest, Go, Dart, JSON, Elixir, and Rust code
在Chromium的Network选项卡左边的Name栏中找到?page=1
项目,右击选择Copy->Copy as cURL(bash)
,然后粘帖到该网页的curl command
栏中,语言选择Python
,右边会实时生成一段Python
脚本,是用Requests
库的复现,直接复制后运行,然后打印response.json()
,发现数据被成功获取。
2.4 编写items.py
import scrapyclass XuetangxItem(scrapy.Item):# define the fields for your item here like:name = scrapy.Field()teachers = scrapy.Field()school = scrapy.Field()count = scrapy.Field()
2.5 编写spider.py
在
Scrapy
下的POST
需要使用FormRequest()
手动发送请求。默认的Request
(包含使用start_urls
)都是使用GET
方法,本例中的接口只能使用POST
方法,使用GET
(包括使用浏览器访问接口的URL)会返回一个包含错误消息的json
.FormRequest()
的参数在scrapy
不同版本之间有变化,最新版本中几个常用的参数如下url
:必需参数。- 需要注意
Scrapy
并不支持params
属性,即参数不能自动填写。接口的地址https://www.xuetangx.com/api/v1/lms/get_product_list/?page={}
在Requests
库中可以写成url = 'https://www.xuetangx.com/api/v1/lms/get_product_list/', params = (('page',page_number),)
。在Scrapy
中就不可以,需要自己格式化字符串构造地址。(也可以使用urllib
)
- 需要注意
headers
:指定请求头。本例中需要使用,不然会返回空结果。method
: 请求方法,可以是GET
或者POST
,本例中使用POST
.body
: 需要POST
的表单数据,即Chromium中的Request Payload
.callback
: 回调函数,指定本请求完成后的item
由谁处理。
由于需要手动创造请求,需要重写
spider
的start_requests
方法,在此处发送所有的请求到引擎。同时需要注意此时返回的是一个
json
对象的二进制,需要使用json
模块进行相应的模块,比xpath
操作HTML更直观。import scrapyimport jsonfrom pprint import pprintfrom xuetangx.items import XuetangxItemclass XuetangxSpider(scrapy.spiders.Spider):name = "xuetangx"allowed_domains = ["xuetangx.com/"]url_pat = 'https://www.xuetangx.com/api/v1/lms/get_product_list/?page={}'data = '{"query":"","chief_org":[],"classify":["1"],"selling_type":[],"status":[],"appid":10000}'headers = {'django-language': 'zh',# 填写自己的Headers,此处仅做提示用'referer': 'https://www.xuetangx.com/search?query=&org=&classify=1&type=&status=&page=1','authority': 'www.xuetangx.com',}# 不使用start_urls列表,因为要创建POST请求def start_requests(self):for page in range(1,5+1):yield scrapy.FormRequest(url = self.url_pat.format(page),headers = self.headers,method = 'POST',body = self.data,callback= self.parse)def parse(self, response):j = json.loads(response.body)for product in j['data']['product_list']:item = XuetangxItem()item['name'] = product['name']teacher_name_list = []for teacher in product['teacher']:teacher_name_list.append(teacher['name'])item['teachers'] = ','.join(teacher_name_list)item['school'] = product['org']['name']item['count'] = product['count']yield item
2.6 编写pipelines.py
本题要求存入
csv
文件中,需要使用csv
模块。为了避免出现空行(CRLF问题),在打开文件
open
时需要指定newline=''
import csvclass XuetangxPipeline:def open_spider(self, spider):try:self.file = open('xuetangx.csv','w',newline='')self.csv = csv.writer(self.file)except Exception as err:print(err)def process_item(self, item, spider):self.csv.writerow(list(item.values()))return itemdef close_spider(self, spider):self.file.close()
2.7 结果展示
- 由于我在处理时将多位老师的名字用逗号分隔存储,而
csv
的分隔符是逗号,所以包含逗号的字符串用引号括了起来。 - 打开处理管道。很重要,不打开的话,
spider.py
的parse
的结果不会传给pipelines.py
,结果只是在终端打印一下而没有持久化。 数据科学导论,"袁博,何隽",清华大学,48659大学计算机基础,卫春芳,湖北大学,46641基于Linux的C++,乔林,清华大学,45886大学计算机基础,"徐红云,刘欣欣,曹晓叶",华南理工大学,45091……
[Python程序设计] 用Scrapy爬取学堂在线计算机类课程页面的信息相关推荐
- 学堂在线 python_Python作业1:Scrapy爬取学堂在线+链家二手房
import scrapy import json from pprint import pprint from studyHall.items import StudyhallItem class ...
- 七、Python简单爬取学堂在线合作院校页面内容
这是一个大学生的爬虫作业,我是收钱干活的,比较简单,来过来分享一下. 就是要爬取到合作院校的名称及该所院校在学堂在线开课的数量,将爬取到的数据保存到一个json文件中!例如:"{" ...
- scrapy 解析css,Scrapy基础(六)————Scrapy爬取伯乐在线一通过css和xpath解析文章字段...
上次我们介绍了scrapy的安装和加入debug的main文件,这次重要介绍创建的爬虫的基本爬取有用信息 通过命令(这篇博文)创建了jobbole这个爬虫,并且生成了jobbole.py这个文件,又写 ...
- [Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(四) —— 应对反爬技术(选取 User-Agent、添加 IP代理池以及Cookies池 )
上一篇:[Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(三) -- 数据的持久化--使用MongoDB存储爬取的数据 最近项目有些忙,很多需求紧急上线,所以一直没能完善< 使用 ...
- [Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(二) —— 编写一个基本的 Spider 爬取微博用户信息
上一篇:[Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(一) -- 新建爬虫项目 在上一篇我们新建了一个 sina_scrapy 的项目,这一节我们开始正式编写爬虫的代码. 选择目标 ...
- [Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(三) —— 数据的持久化——使用MongoDB存储爬取的数据
上一篇:[Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(二) -- 编写一个基本的 Spider 爬取微博用户信息 在上一篇博客中,我们已经新建了一个爬虫应用,并简单实现了爬取一位微 ...
- Scrapy爬取伯乐在线所有文章
Scrapy爬取伯乐在线所有文章 1.目标分析 2.Spiders的编写 2.1.网站结构分析 2.2.获取当页文章URL 2.3.获取文章的信息 2.4.文章列表下一页 2.4.编写spiders. ...
- Scrapy实例————爬取学堂在线合作院校页面内容
目标 通过Scrapy爬取到合作院校的名称及该所院校在学堂在线开课的数量,将爬取到的数据保存到一个json文件中,例如:"清华大学,308",地址 http://www.xueta ...
- Scrapy爬取伯乐在线的所有文章
本篇文章将从搭建虚拟环境开始,爬取伯乐在线上的所有文章的数据. 搭建虚拟环境之前需要配置环境变量,该环境变量的变量值为虚拟环境的存放目录 1. 配置环境变量 2.创建虚拟环境 用mkvirtualen ...
- scrapy | 爬取伯乐在线全部博文(xpath/css/itemload三种提取方法,同步、异步方式存入MySQL)
1.目标 伯乐在线网站地址:http://blog.jobbole.com/all-posts/ 爬取伯乐在线的所有文章信息,包括图片网址,标题,发表日期,标签,点赞数,评论数等 将爬取的数据保存至数 ...
最新文章
- mysql和oracle执行计划_mysql explain执行计划详解
- 新手用python2还是3-新手用python2还是3
- 计算字符串相似度算法—Levenshtein
- tensorflow: Could not load dynamic library ‘cudart64_101.dll‘ 解决办法
- C++中 引用与取地址的区别
- C语言有参函数调用时参数间数据传递问题
- 须使用visual c 内联汇编语言开发,在VisualC 中使用内联汇编
- java this() super()_java中的this和super
- 无线文件服务器,文件共享新方法 无线网络文件共享设置
- 长沙中职英语计算机等级考试查询,湖南省中等职业教育公共基础课达标训练英语291-300...
- QT每日一练day25:触发绘画事件
- python制作表格的语句_python根据Excel自动生成创建表sql语句
- HTML5新增input表单(HTML5)
- 谷歌浏览器下载更新(附带谷歌安装包百度云)
- 电动自行车新国标正式发布,推动电池产业转型升级
- spark的三种部署模式
- 项目管理 : 项目管理技术的七大优势
- C语言实验——逆置正整数
- win10安装wsl步骤
- 情人节的自娱自乐——情书事件
热门文章
- teamviewer13试用期已到期,错装商业版怎么还原成个人版?
- Linux stress命令详解
- apk部分手机安装失败_安装APK文件时提示“解析包出现错误”,看完就知道怎么做了!...
- 显微镜下的大明内容_《显微镜下的大明》读后感1000字
- Http405错误,方法类型也没有错,解决办法
- Pytorch版Lookahead使用及遇到的问题
- 自媒体行业的发展和前景
- 计算机专业论文要怎么写,计算机专业本科生论文摘要怎么写 计算机专业本科生论文摘要范文参考...
- Pr 入门教程如何倾斜移位效果?
- redis-trib.rb操作命令