在python课上布置的作业,第一次进行爬虫,走了很多弯路,也学习到了很多知识,借此记录。

1. 获取学堂在线合作院校页面

要求

爬取学堂在线的计算机类课程页面内容。

要求将课程名称、老师、所属学校和选课人数信息,保存到一个csv文件中。

链接:https://www.xuetangx.com/search?query=&org=&classify=1&type=&status=&page=1

1.确定目标

打开页面,通过查看网页源代码并没有相关内容。可以猜测具体数据由前端通过ajax请求后端具体数据。在开发者工具中,捕获了如下的json数据:

可以看到这个就是我们要求的json数据。考虑如何获取json数据并取出来,分析一下浏览器的请求,将cURL命令转换成Python请求如下:

import requests

cookies = {
'provider': 'xuetang',
'django_language': 'zh',
} headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'zh',
'Content-Type': 'application/json',
'django-language': 'zh',
'xtbz': 'xt',
'x-client': 'web',
'Origin': 'https://www.xuetangx.com',
'Connection': 'keep-alive',
'Referer': 'https://www.xuetangx.com/search?query=&org=&classify=1&type=&status=&page=1',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'TE': 'Trailers',
} params = (
('page', '1'),
) data = '{query:,chief_org:[],classify:[1],selling_type:[],status:[],appid:10000}' response = requests.post('https://www.xuetangx.com/api/v1/lms/get_product_list/', headers=headers, params=params, cookies=cookies, data=data) #NB. Original query string below. It seems impossible to parse and
#reproduce query strings 100% accurately so the one below is given
#in case the reproduced version is not "correct".
# response = requests.post('https://www.xuetangx.com/api/v1/lms/get_product_list/?page=1', headers=headers, cookies=cookies, data=data)

分析请求的网页是https://curl.trillworks.com/,可以在浏览器的开发工具里,选择network选项卡(chrome)或者网络选项卡(Firefox),右键点击某个请求文件,在菜单中选择复制→复制为cURL命令,然后到这个网页中粘贴转换为python的request即可

2.设计爬虫

要选取的数据为课程名称、老师、所属学校和选课人数。设计的items.py如下:

# items.py
import scrapy class XuetangItem(scrapy.Item):
name = scrapy.Field()
teachers = scrapy.Field()
school = scrapy.Field()
count = scrapy.Field()
pass

接下来是重头戏设计spider.py文件。因为爬取的是json数据而不是html静态页面,需要设计start_requests函数来发送请求。结合之前分析的Python request,具体代码如下:

import scrapy
import json
from xuetang.items import XuetangItem class mySpider(scrapy.spiders.Spider):
name = "xuetang"
allowed_domains = ["www.xuetangx.com/"]
url = "url_pat = 'https://www.xuetangx.com/api/v1/lms/get_product_list/?page={}'"
data = '{"query":"","chief_org":[],"classify":["1"],"selling_type":[],"status":[],"appid":10000}'
# data由分析中得来
headers = {
'Host': 'www.xuetangx.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0',
'authority': 'www.xuetangx.com',
'Accept': 'application/json,text/plain,*/*',
'Accept-Language': 'zh',
'Accept-Encoding': 'gzip, deflate, br',
'django-language': 'zh',
'xtbz': 'xt',
'content-type': 'application/json',
'x-client': 'web',
'Connection': 'keep-alive',
'Referer': 'https://www.xuetangx.com/university/all',
'Cookie': 'provider=xuetang; django_language=zh',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache'
}
# 直接从浏览器抄过来,防止服务器辨析到不是浏览器而导致失败 def start_requests(self):
for page in range(1, 6):
yield scrapy.FormRequest(
url=self.url.format(page),
headers=self.headers,
method='POST',
# 浏览器的请求是POST,而且响应头中写明只允许POST
body=self.data,
callback=self.parse
) def parse(self, response):
j = json.loads(response.body)
for each in j['data']['org_list']:
item = XuetangItem()
item['name'] = each['name']
item['school'] = each['org']['name']
item['count'] = each['count']
teacher_list = []
for teacher in each['teacher']:
teacher_list.append(teacher['name'])
# 因为有些课程有多个老师,需要逐个保存,写入一条记录里
item['teacher'] = ','.join(teacher_list)
yield item

然后设计pipelines.py文件,将爬取到的数据保存为csv文件:

import csv

class XuetangPipeline(object):
dict_data = {'data': []} def open_spider(self, spider):
try:
self.file = open('data.csv', "w", encoding="utf-8", 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 item def close_spider(self, spider):
self.file.close()

这样就可以就行爬虫了,当然还要在setting.py中设置ITEM_PIPELINES。之后可以命令行启动爬虫,也可以运行执行cmd命令的python文件:

from scrapy import cmdline
cmdline.execute("scrapy crawl xuetang".split())

3.数据展示

保存的csv文件内容如下,正好内容为50条,这里仅展示开头一部分:

C++语言程序设计基础,清华大学,424718,"郑莉,李超,徐明星"
数据结构(上),清华大学,411298,邓俊辉
数据结构(下),清华大学,358804,邓俊辉
……

2. 获取链家二手房信息

要求:

爬取链家官网二手房的数据 https://bj.lianjia.com/ershoufang/

要求爬取北京市东城、西城、海淀和朝阳四个城区的数据(每个区爬取5页),将楼盘名称、总价、平米数、单价保存到json文件中。

1.确定目标

打开网页,查看网页源代码,可以看到在源代码中间已经包含了二手房信息,说明页面由后端渲染完毕后返回到浏览器,这样可以通过Xpath来爬取相关内容。分析一下某个楼盘的信息结构:

<html>
<head></head>
<body>
<a class="noresultRecommend img LOGCLICKDATA" href="https://bj.lianjia.com/ershoufang/101109392759.html" target="_blank" data-log_index="1" data-el="ershoufang" data-housecode="101109392759" data-is_focus="" data-sl="">
<!-- 热推标签、埋点 -->
<img src="https://s1.ljcdn.com/feroot/pc/asset/img/vr/vrgold.png?_v=202011171709034" class="vr_item" /><img class="lj-lazy" src="https://image1.ljcdn.com/110000-inspection/pc1_hAjksKeSW_1.jpg.296x216.jpg" data-original="https://image1.ljcdn.com/110000-inspection/pc1_hAjksKeSW_1.jpg.296x216.jpg" alt="北京西城长椿街" style="display: block;" /></a>
<div class="info clear">
<div class="title">
<a class="" href="https://bj.lianjia.com/ershoufang/101109392759.html" target="_blank" data-log_index="1" data-el="ershoufang" data-housecode="101109392759" data-is_focus="" data-sl="">槐柏树街南里 南北通透两居室 精装修</a>
<!-- 拆分标签 只留一个优先级最高的标签-->
<span class="goodhouse_tag tagBlock">必看好房</span>
</div>
<div class="flood">
<div class="positionInfo">
<span class="positionIcon"></span>
<a href="https://bj.lianjia.com/xiaoqu/1111027374889/" target="_blank" data-log_index="1" data-el="region">槐柏树街南里 </a> -
<a href="https://bj.lianjia.com/ershoufang/changchunjie/" target="_blank">长椿街</a>
</div>
</div>
<div class="address">
<div class="houseInfo">
<span class="houseIcon"></span>2室1厅 | 60.81平米 | 南 北 | 精装 | 中楼层(共6层) | 1991年建 | 板楼
</div>
</div>
<div class="followInfo">
<span class="starIcon"></span>226人关注 / 1个月以前发布
</div>
<div class="tag">
<span class="subway">近地铁</span>
<span class="isVrFutureHome">VR看装修</span>
<span class="five">房本满两年</span>
<span class="haskey">随时看房</span>
</div>
<div class="priceInfo">
<div class="totalPrice">
<span>600</span>万
</div>
<div class="unitPrice" data-hid="101109392759" data-rid="1111027374889" data-price="98668">
<span>单价98668元/平米</span>
</div>
</div>
</div>
<div class="listButtonContainer">
<div class="btn-follow followBtn" data-hid="101109392759">
<span class="follow-text">关注</span>
</div>
<div class="compareBtn LOGCLICK" data-hid="101109392759" log-mod="101109392759" data-log_evtid="10230">
加入对比
</div>
</div>
</body>
</html>

可以看到房子的名称在class="title"的div下的a标签内,平米数保存在class="houseInfo"的div里,但需要截取一下字符串,单价和总价均保存在class="priceInfo"的div中,有趣的是有些信息没有单价显示,即span里的元素为空,但是观察到其父元素div内有一个属性data-price,其值正好等于单价,因此提取这个即可。

2.设计爬虫

需要保存的数据为楼盘名字、平米数、总价、单价。items.py如下:

import scrapy

class YijiaItem(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()
square = scrapy.Field()
price = scrapy.Field()
total = scrapy.Field()
pass

分析要爬虫的页面,网页提供了选择区的筛选,点击“西城区”后网页地址变为了https://bj.lianjia.com/ershoufang/xicheng/,因此可以将网页地址的变动部分用format去填充。spider.py的内容如下:

from yijia.items import YijiaItem
import scrapy class mySpider(scrapy.spiders.Spider):
name = 'lianjia'
allowed_domains = ["bj.lianjia.com/"]
url = "https://bj.lianjia.com/ershoufang/{}/pg{}/"
# 第一个地方为地区,第二个为页数
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
}
#抄来浏览器的header def start_requests(self):
positions = ["dongceng", "xicheng", "chaoyang", "haidian"]
for position in positions:
for page in range(1, 6):
yield scrapy.FormRequest(
url=self.url.format(position, page),
method="GET",
headers=self.headers,
callback=self.parse
) def parse(self, response):
for each in response.xpath("/html/body/div[4]/div[1]/ul/li"):
item = YijiaItem()
item['name'] = each.xpath("div[1]/div[1]/a/text()").extract()[0]
house_info = each.xpath("div[1]/div[3]/div[1]/text()").extract()[0].split('|')
item['square'] = house_info[1].strip()
item['total'] = each.xpath("div[1]/div[6]/div[1]/span/text()").extract()[0] + "万元"
item['price'] = each.xpath("div[1]/div[6]/div[2]/@data-price").extract()[0] + "元/平米"
yield item

然后是设计管道文件,将内容保存为一个json文件:

import json

class YijiaPipeline(object):
dict_data = {'data': []} def open_spider(self, spider):
try:
self.file = open('data.json', "w", encoding="utf-8")
except Exception as err:
print(err) def process_item(self, item, spider):
dict_item = dict(item)
self.dict_data['data'].append(dict_item)
return item def close_spider(self, spider):
self.file.write(json.dumps(self.dict_data, ensure_ascii=False, indent=4, separators=(',', ':')))
self.file.close()

最后仿照前一个样例进行爬虫即可。

3.数据展示

保存的json文件内容如下所示,这里只提供前三条供展示:

{
"data":[
{
"name":"此房南北通透格局,采光视野无遮挡,交通便利",
"square":"106.5平米",
"total":"1136万元",
"price":"106667元/平米"
},
{
"name":"新安南里 南北通透 2层本房满五年唯一",
"square":"55.08平米",
"total":"565万元",
"price":"102579元/平米"
}
/*省略之后的N条数据*/
]
}

python爬虫分析报告的更多相关文章

  1. Python爬虫——Python 岗位分析报告

    前两篇我们分别爬取了糗事百科和妹子图网站,学习了 Requests, Beautiful Soup 的基本使用.不过前两篇都是从静态 HTML 页面中来筛选出我们需要的信息.这一篇我们来学习下如何来获 ...

  2. python爬虫——分析天猫iphonX的销售数据

    01.引言 这篇文章是我最近刚做的一个项目,会带领大家使用多种技术实现一个非常有趣的项目,该项目是关于苹果机(iphoneX)的销售数据分析,是网络爬虫和数据分析的综合应用项目.本项目会分别从天猫和京 ...

  3. 04爬取拉勾网Python岗位分析报告

    # 导入需要的包import requestsimport time,randomfrom openpyxl import Workbookimport pymysql.cursors#@ 连接数据库 ...

  4. Python 爬虫利器 Selenium 介绍

    Python 爬虫利器 Selenium 介绍 转 https://mp.weixin.qq.com/s/YJGjZkUejEos_yJ1ukp5kw 前面几节,我们学习了用 requests 构造页 ...

  5. 学习笔记之Python爬虫

    Python 爬虫介绍 | 菜鸟教程 http://www.runoob.com/w3cnote/python-spider-intro.html https://blog.csdn.net/sina ...

  6. Python爬虫和情感分析简介

    摘要 这篇短文的目的是分享我这几天里从头开始学习Python爬虫技术的经验,并展示对爬取的文本进行情感分析(文本分类)的一些挖掘结果. 不同于其他专注爬虫技术的介绍,这里首先阐述爬取网络数据动机,接着 ...

  7. 推荐一个利用 python 生成 pptx 分析报告的工具包:reportgen

    reportgen v0.1.8 更新介绍 这段时间,我对 reportgen 进行了大工程量的修改和更新.将之前在各个文章中出现的函数进行了封装,同时也对现有工具包的一些逻辑进行了调整. 1.rep ...

  8. python 生成 pptx 分析报告的工具包:reportgen

    python机器学习-sklearn挖掘乳腺癌细胞( 博主亲自录制) 网易云观看地址 https://study.163.com/course/introduction.htm?courseId=10 ...

  9. python爬虫之分析Ajax请求抓取抓取今日头条街拍美图(七)

    python爬虫之分析Ajax请求抓取抓取今日头条街拍美图 一.分析网站 1.进入浏览器,搜索今日头条,在搜索栏搜索街拍,然后选择图集这一栏. 2.按F12打开开发者工具,刷新网页,这时网页回弹到综合 ...

随机推荐

  1. CSDN的Markdown编辑器实用技巧(傻瓜式教程)

    markdown编辑器被很多人声称是可以取代word的文字编辑器,其优点我们在这就不再过多赘述了,但对于一些初次接触的人来说,或多或少都有还些不适应,其主要原因在于一些常见的功能突然不知道怎么实现,所 ...

  2. Bitmap缩放(二)

    先得到位图宽高不用加载位图,然后按ImageView比例缩放,得到缩放的尺寸进行压缩并加载位图.inSampleSize是缩放多少倍,小于1默认是1,通过调节其inSampleSize参数,比如调节为 ...

  3. 老板,来几道web玩玩

    好久没做web了,没想到还能自己做出来555 [MRCTF2020]Ez_bypass 签到题8 给了源码,一个md5强类型比较,然后post传参,弱类型判断,直接1234567a绕过了 I put ...

  4. IPEX-1代/3代/4代/5代,PCB天线底座,公头,样式及封装尺寸图

    1.IPEX-1代,PCB天线底座 2.IPEX-3代,PCB天线底座 3.IPEX-4代,PCB天线底座 4.IPEX-5代,PCB天线底座

  5. npm ande gulp cmd

    在学习前,先谈谈大致使用gulp的步骤,给读者以初步的认识.首先当然是安装nodejs,通过nodejs的npm全局安装和项目安装gulp,其次在项目里安装所需要的gulp插件,然后新建gulp的配置 ...

  6. pandas dataframe 时间字段 diff 函数

    pandas pandas 是数据处理的利器,非常方便进行表格数据处理,用过的人应该都很清楚,没接触的可以自行查阅pandas 官网. 需求介绍 最近在使用 pandas 的过程中碰到一个问题,需要计 ...

  7. MongoDB 数据备份和恢复 --- MongoDB基础用法(七)

    数据备份 在Mongodb中我们使用mongodump命令来备份MongoDB数据.该命令可以导出所有数据到指定目录中. mongodump命令可以通过参数指定导出的数据量级转存的服务器. mongo ...

  8. django 框架模型之models常用的Field

    1. django 模型models 常用字段          1.models.AutoField 自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列 如果要显式的自定义一 ...

  9. 热部署只知道devtools吗?JRebel不香吗?

    持续原创输出,点击上方蓝字关注我 目录 前言 JRebel收费怎么破? 什么是本地热部署? 什么是远程热部署? JRebel和devtools的区别 如何安装JRebel? 如何本地热部署? 如何远程 ...

  10. Antisymmetry

    题意描述 Antisymmetry 求给定的字符串的子串集合中为"反对串"的个数. 反对串的定义为,将这个字符串 \(0\) 和 \(1\) 取反后,再将整个串反过来和原串一样,就 ...