首页 >> 实验教学 >> 实验项目 >> 详细内容
实验教学
 
实验项目 >> 正文
网络爬虫实验指导
日期:2021-12-09 17:23:48  发布人:nclgjsj  浏览量:543

 

总共六个实验:

实验一: 初识网络爬虫(Python的基础复习)

Python的基础知识练习(实验目的:画一个七段数码管)

实验二: 静态网页数据的爬取(抓取豆瓣网的TOP250的数据)

实验三:网页数据的分析  P77

       (练习使用BeautifulSoup)来分析网页的数据

练习爬取  求职信息

实验四: 网页数据存储

实验五: 常规动态网页数据爬取

实验六:综合案例(https://www.imooc.com/article/284622

实验一: 初识网络爬虫(Python的基础复习)

Python的基础知识练习(实验目的:画一个七段数码管)

实验目的掌握函数的基本使用

掌握使用turtle库绘制图形

实验设备计算机、windows7、Python、Jupyter

实验课时2课时

实验地点专业机房

实验内容:

任务一:计算圆的面积

 

任务二: 绘制环形

import turtle as ttt

ttt.pensize(2)

ttt.pencolor("red")

ttt.circle(10)

ttt.circle(40)

ttt.circle(80)

ttt.circle(160)

 

 

任务三:绘制五角星

from turtle import *

color('red','yellow')

begin_fill()

for i in range(5):

    fd(200)

    rt(144)

end_fill()

 

任务四:绘制七段数码管

 

1编写一个函数来绘制一条线并且给它一个状态值设定它的状态.

import turtle as t

def drawline(draw):

t.pendown() if draw else t.penup()

 t.fd(40)

    t.right(90)

2反复调用这个函数进而绘制出一个七段数码管:

 

def drawdigit(digit):#根据数值绘制七段数码管

    drawline(True) if dight in [2,3,4,5,6,8,9] else drawline(False)

    drawline(True) if dight in [0,1,3,4,5,6,7,8,9] else drawline(False)

    drawline(True) if dight in [0,2,3,5,6,8,9] else drawline(False)

    drawline(True) if dight in [0,2,6,8] else drawline(False)

    t.left(90)

    drawline(True) if dight in [0,4,5,6,8,9] else drawline(False)

    drawline(True) if dight in [0,2,3,5,6,7,8,9] else drawline(False)

    drawline(True) if dight in [2,3,4,5,6,8,9] else drawline(False)

    drawline(True) if dight in [0,1,2,3,4,7,8,9] else drawline(False)

t.left(180)

t.pu()#为绘制后续数字确定位置

t.fd(20)#为绘制后续数字确定位置

 

编写一个日期函数,输出根据日期显示数码管

def drawdate(date):#获取日期

    for i in date:

        drawdigit(eval(i))#通过eval()将数字变成整数

def main(date):

    t.setup(800,350,200,200)

    t.pu()

    t.fd(-300)

    t.pensize(5)

    t.color("red")

    drawdate(date)

    t.hideturtle()

    t.done()

main(input("请输入一个年月日,与阿拉伯数字形式不加任何标点的形式输入,例:20190122:\n"))

 

实验结果及总结:

   自己根据自己的情况编写

 

实验二: 静态网页数据的爬取(抓取豆瓣网的TOP250的数据)

实验目的

掌握使用requests库生成GET请求

掌握使用requests库上传请求头中的User-Agent信息

掌握使用requests库查看返回的请求头

掌握使用requests库查看返回的状态码

掌握使用requests库识别网页页面内容编码,并正确显示页面内容

实验设备计算机、windows7、Python、Jupyter

实验课时2课时

实验地点专业机房

实验内容:

任务一:打开中国旅游网页, Ctrl+U访问源代码

1、任务步骤:

  • 确定爬取的目标网页链接。
  • pycharm中编写代码实现爬虫功能。

2、任务提交要求:

  • 提交爬取的目标网站页面截图。
  • 提交爬取的代码以及运行结果的截图。
  • 程序第一行为注释,内容为:小组+姓名

 

任务二:读取百度等网站的robots.txt协议

1、任务步骤:

  • 确定爬取的目标网页链接。
  • pycharm中编写代码实现爬虫功能。

2、任务提交要求:

  • 提交爬取的目标网站页面截图。
  • 提交爬取的代码以及运行结果的截图。
  • 程序第一行为注释,内容为:小组+姓名

 

任务三:打开有道翻译,用开发者模式访问网页

1、任务步骤:

  • 打开有道翻译,按F12键,进入开发者模式。
  • 在有道翻译页面,输入:我爱中国,翻译成英文。
  • 进入开发者模式中的network,找到url和  headers 内容,复制user-agent和url信息。

2、任务提交要求:

  • 提交爬取的目标网站页面截图。
  • 提交爬取的代码以及运行结果的截图。
  • 程序第一行为注释,内容为:小组+姓名

 

任务四:编写代码,用requests库实现爬取豆瓣电影官网的页面

1、任务步骤:

  • 确定爬取的目标网页链接。
  • pycharm中编写代码实现爬虫功能。

2、任务提交要求:

  • 提交爬取的目标网站页面截图。

提交爬取的代码以及运行结果的截图。

程序第一行为注释,内容为:小组+姓名

程序内容:读取第一页内容代码: 可以定义一个函数 get_movies()

import requests

 

def get_movies():

#定义headers头部标题

headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36','Host': 'movie.douban.com'}

#定义链接地址,从第一页开始

    link='https://movie.douban.com/top250?start=0’

    r=requests.get(link, headers=headers,timeout= 10)

    print("第一页的响应状态码是:",r.status_code)

    print(r.text)

 

get_movies()

 

任务五:编写代码,用requests库实现爬取豆瓣电影TOP250的详细页面

1、任务步骤:

  • 确定爬取的目标网页链接。
  • Jupyter中编写代码实现爬虫功能。

2、任务提交要求:

  • 提交爬取的目标网站页面截图。

提交爬取的代码以及运行结果的截图。

程序第一行为注释,内容为:小组+姓名

3、程序内容:读取第23等页内容的代码。发现规律如下:

link='https://movie.douban.com/top250?start=0’

                                     修改start=25  .

 

1)编写代码如下:

import requests

 

def get_movies():

#定义headers头部标题

headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36','Host': 'movie.douban.com'}

#定义链接地址,修改start=25,从第二页开始

    link='https://movie.douban.com/top250?start=25’

    r=requests.get(link, headers=headers,timeout= 10)

    print("第一页的响应状态码是:",r.status_code)

    print(r.text)

 

get_movies()

 

2)增加循环语句,读取前10页代码:(每页25条, 可以使用i*25 表示第几页信息)

import requests

 

def get_movies():

    headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36','Host': 'movie.douban.com'}

    for i in range(0,10):

        link='https://movie.douban.com/top250?start='+ str( i*25 )

        r=requests.get(link, headers=headers,timeout= 10)

        print( str(i+1), "页的响应状态码是:",r.status_code)

        print(r.text)

 

get_movies()

 

 3)编写代码,学习处理分析数据  使用BeautifulSoup

通过分析数据: 解析HTML代码,发现电影名在:

 

 

 

找到需要分析的代码在:

<div class="hd">

     <a href="https://movie.douban.com/subject/1292052/" class="">

     <span class="title">肖申克的救赎</span>

     <span class="title"> / The Shawshank Redemption</span>

     <span class="other"> / 月黑高飞()  /  刺激1995()</span>

    </a>

<span class="playable">[可播放]</span>

</div>

 

如果需要导演的话,在<div class=bd>中。

#1导入BeautifulSoup库, ,提取电影名称

From bs4 import BeautifulSoup

#2定义读取电影页面的程序

#3 定义列表,准备将电影名存入  list

movie_list = []

#分析所有的html标记

  具体代码如下:

import requests

from bs4 import BeautifulSoup

 

def get_movies():

    headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36','Host': 'movie.douban.com'}

    link='https://movie.douban.com/top250?start=25'

    r=requests.get(link, headers=headers,timeout= 10)

print("第一页的响应状态码是:",r.status_code)

print(r.text)

     

    #3 定义列表,准备将电影名存入  list

    movie_list = []

    #分析所有的html标记

    soup = BeautifulSoup(r.text,"lxml" )

    div_list = soup.find_all('div', class_="hd")

    print(div_list)

 

get_movies()

 

 

 

增加数据清洗代码:

import requests

from bs4 import BeautifulSoup

 

def get_movies():

    headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36','Host': 'movie.douban.com'}

    link='https://movie.douban.com/top250?start=25'

    r=requests.get(link, headers=headers,timeout= 10)

print("第一页的响应状态码是:",r.status_code)

#3 定义列表,准备将电影名存入  list

    movie_list = []

    #分析所有的html标记

    soup = BeautifulSoup(r.text,"lxml" )

div_list = soup.find_all('div', class_="hd")

#增加数据清洗代码,读取电影标题

    for each in div_list:

        movie=each.a.span.text.strip()

        movie_list.append(movie)

    return movie_list

    

movies=get_movies()

print(movies) 

 

     

    

4、再加入循环之后爬取的资料:

#定义一个函数4,找到若干页的电影名称

def get_movies4():

    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36','Host': 'movie.douban.com'}

    movies_list=[]

    for i in range(0,10):

        url='https://movie.douban.com/top250?start='+str(i*25)

        r=requests.get(url, headers=headers,timeout= 10)

        print("第一页的响应状态码是:",r.status_code)

       

        soup = BeautifulSoup(r.text,"lxml" )

        div_list = soup.find_all('div', class_="hd")

 

        for each in div_list:

            movie=each.a.span.text.strip()

            movies_list.append(movie)

return movies_list

movies=get_movies4()

prin t(movies)

 

 

实验三:网页数据的分析

实验目的掌握使用练习使用BeautifulSoup)来分析网页的数据

掌握使用re库分析数据中所需要的材料

掌握获取“江南人才网“的数据信息,并读取职位,月薪,公司,地址等信息

掌握将资料存入记事本文件中

实验设备计算机、windows7、Python、Jupyter

实验课时2课时

实验地点专业机房

实验内容:

任务一:练习  re和 BeautifulSoup两个内容(所有代码,ctrl+U,下载)

1、导入正则表达式和BeautifulSoup

import re

from bs4 import BeautifulSoup

2、引入 html代码

html01=''' html代码  '''

soup.BeautifulSoup(html01, 'lxml')

3、简单的打印出来

print( soup.a.string)

 

4、查找所有   a 标签

print(soup.find_all('a'))

print(soup.find_all([‘span’,’a’]))

也可以使用:

newstitle=soup.find_all('a')

print(newstitle)

 

 

5、单独打印新闻标题

for each in newstitle:

    word=each.string

print(word)

 

任务二:访问湖南人才网:http://www.hnrcsc.com/    

找到:职位名称、公司名称、工作地点、更新日期、薪资范围

方法:1、网页数据获取 2、数据解析   3、存储

可以将所有的代码直接下载下来

1、导入正则表达式和BeautifulSoup

import re

from bs4 import BeautifulSoup

 

 

1、简化版如下:

import re

#查找所有的工作岗位

pos=soup.find_all('a',href=re.compile('/web/view/view-recruit/id/'))

print(pos)

pos_all=[]

将每个工作岗位存入到pos_all列表中

for i in range(0,len(pos)):

    pos_all.append(pos[i].string)

print(pos_all)

 

#同理,也可以查找工作待遇,工作待遇在<font class=detail>标签中

detail=soup.find_all('tr',class_='detail')

for each in detail:

    daiyu=each.font.string

    print(daiyu)

 

#查找更多的详细信息:详细信息在<tr>标签中

pos2=soup.find_all('tr')

print(pos2)

 

写入文件的时候,注意加上编码,否则容易出错

#!/usr/bin/python

# -*- coding: UTF-8 -*-

file = open("abc.txt", "w", encoding='utf-8')

for i in range(0,len(pos_all)):

    file.write(pos_all[i]+'\n')

 

任务三:也可以通过定义函数执行下面的代码实现完整内容:

 

效果 如下:

 

 

 

实验四: 网页数据存储

实验目的

掌握使用 PyMongo 库、PyMySQL 库存储数据。

掌握将数据存储到文件中的方法

实验设备计算机、windows7、Python、Jupyter

实验课时2课时

实验地点专业机房

实验内容:

1. 掌握 文本存储的方法

2. 掌握 CSV格式的存储方法

3. 掌握使用 PyMySQL 库将获取的数据存 储入 MySQL 数据库

4. 掌握使用 PyMongo 库将获取的数据存 储入 MySQL 数据库

实验步骤

1、使用记事本存储信息

1)创建一个文件夹hello

2)输入一下代码,实现添加1.txt记事本,并存入数据的功能。

tit='你好'

with open('c:\\hello\\1.txt',"a+") as f:

    f.write(tit)

    f.close()

3)按照tab键格式输入内容。

output='\t'.join(['编号','姓名','成绩'])

with open('e:\\word\\test02.txt',"a+",encoding="utf-8") as csvf:

    csvf.write(output)

    f.close()

 

2、创建csv格式(excel),读取数据

1)打开excel 文件,输入相应的信息数据

 

2)输入一下代码,读取 csv文件内容,并显示

import csv

with open('e:\\word\\test.csv',"r") as csvf:

    csv_reader=csv.reader(csvf)

    for row in csv_reader:

        print(row)

        print(row[1])

 

3)使用读取的方式读取  csv文件,并写入一行新内容

import csv

output=['11','掌握三','98']

with open('e:\\word\\test.csv',"a+",newline='') as csvf:

    w = csv.writer(csvf)

w.writerow(output)

 

 

3、使用Mysql存储数据:爬取并存储2020中国大学的排名情况

爬取的网址如下:https://www.shanghairanking.cn/rankings/bcur/202011

 

1)爬取并解析网站:

我们需要获取到学校的排名、学校的名称、学校所在的省份、该学校所属的类型以及大学的总分。这些数据都保存在表格当中,因此我选用xpath提取表格数据。

具体代码如下所示:

解析网页提取信息

    def parse_html(self, html):

        rank_ids = []

        university_names = []

        provices = []

        types = []

        all_sorces = []

        html = etree.HTML(html)

        tr_lists = html.xpath('//table/tbody/tr')

        for tr in tr_lists:

            # 大学排名

            rank_id = tr.xpath('./td[1]/text()')[0].split()[0]

            rank_ids.append(rank_id)

 

            # 大学名称

            university_name = tr.xpath('./td[2]/a/text()')[0]

            university_names.append(university_name)

 

            # 省市

            province = tr.xpath('./td[3]/text()')[0].split()[0]

            provices.append(province)

  

            # 类型

            type = tr.xpath('./td[4]/text()')[0].split()[0]

            types.append(type)

 

            # 总分

            all_source = tr.xpath('./td[5]/text()')[0].split()[0]

            all_sorces.append(all_source)

 

        results = zip(rank_ids, university_names, provices, types, all_sorces)

        return results

2)创建数据库

    def create_db(self):

        host = 'localhost'

        user = 'root'

        password = '698350As?'

        port = 3306

        db = pymysql.connect(host=host, user=user, password=password, port=port)

        cursor = db.cursor()

        sql = 'create database unversityrank default character set utf8'

        cursor.execute(sql)

        db.close()

        print('创建成功')

在上面的这段代码中可以看到我创建了一个名为unversityrank的数据库。

 

3)创建表格

 

    def create_tables(self):

        host = 'localhost'

        user = 'root'

        password = '698350As?'

        port = 3306

        db = 'unversityrank'

        db = pymysql.connect(host=host, user=user, password=password, port=port, db=db)

        cursor = db.cursor()

        sql = 'create table if not exists rank4 (id int auto_increment primary key,rankid varchar(255) not null, name varchar(255) not null, province varchar(255) not null, type varchar(255) not null, source varchar(255) not null)'

        cursor.execute(sql)

        db.close()

        print('创建成功')

在上面的这段代码中我成功在数据库unversityrank中创建了表格ranks,并为其创建了字段。

 

在这里需要注意的是,在这个表格中不能使用排名这个字段作为主键,因为不同的学校可能出现相同的排名。

 

4)插入数据

 def save_data(self, results):

        host = 'localhost'

        user = 'root'

        password = '698350As?'

        port = 3306

        db = 'unversityrank'

        db = pymysql.connect(host=host, user=user, password=password, port=port, db=db)

        cursor = db.cursor()

        sql = 'insert into rank4(rankid, name, province, type, source) values(%s,%s,%s,%s,%s)'

        for result in results:

            print(result)

            try:

                cursor.execute(sql, result)

                db.commit()

                print('插入成功')

            except:

                db.rollback()

                print('插入失败')

  

        db.close()

 

至此,便完成了数据的获取及存储。

4、糗事百科 网站论坛数据爬取

现在娱乐类的视频充斥着我们的生活,大家也越来越喜欢在地铁、公交以及茶余饭后的时间刷视频了,那么今天我就拿糗事百科作为例子,提取里面段子的标题、好笑数和作者昵称并保存在csv文件当中。

网址如下:https://www.qiushibaike.com/

 

打开网站之后所呈现的页面如上图所示,需要提取的信息已经框起来了。

1)提取数据

核心代码如下所示:

    def parse_html(self,html):

        pattern_title = re.compile('<div class="recmd-right">.*?<a.*?>(.*?)</a>.*?</div>', re.S)

        title = re.findall(pattern_title, html)

        pattern_funny = re.compile('<div class="recmd-right">.*?<div class="recmd-num">.*?<span>(.*?)</span>', re.S)

        funny = [funny + '好笑' for funny in re.findall(pattern_funny, html)]

        pattern_author = re.compile( '<div class="recmd-right">.*?<div class="recmd-num">.*?<span class="recmd-name">(.*?)</span>', re.S)

        author = re.findall(pattern_author, html)

        datas = [list(data) for data in zip(title, funny, author)]

        return datas

在这里需要要求各位小伙伴具有正则表达式的基础,如果看不懂的话可以参考我前面写的文章。

2)关于翻页

第二页

https://www.qiushibaike.com/8hr/page/2/

 第三页

https://www.qiushibaike.com/8hr/page/3/

 看到上面的内容,想必大家已经非常明白,翻页之后URL的变化规律了吧。

 

3)保存数据

这次我们是将提取到的数据保存到csv文件里面,因此在开始之前先要导入csv模块.

import csv

保存数据的核心代码如下所示:

    for page in range(1, 14):

        url = f'https://www.qiushibaike.com/8hr/page/{page}/'

        html = qiushi.get_html(url)

        datas = qiushi.parse_html(html)

        with open('data.csv', 'a', encoding='utf-8-sig') as f:

            writer = csv.writer(f)

            writer.writerow(['标题', '好笑', '作者'])

            for data in datas:

                writer.writerow(data)

通过上面的代码,可以看到我要获取的是113页的数据,并通过writerow()函数将每一行数据依次写入表格当中。

 

结果展示

 

 

实验五: 常规动态网页数据爬取

实验目的掌握使用直接从JavaScript中采集加载的数据

掌握直接从浏览器中采集已经加载好的数据、即可以使用无界面的浏览器如PhantomJS来解析JavaScript

实验设备计算机、windows7、Python、Jupyter

实验课时2课时

实验地点专业机房

实验内容:

对于动态页面信息的爬取,一般分为两种方法,一种是直接从JavaScript中采集加载的数据、需要自己去手动分析Ajax请求来进行信息的采集,另一种是直接从浏览器中采集已经加载好的数据、即可以使用无界面的浏览器如PhantomJS来解析JavaScript

1、直接从JavaScript中采集加载的数据

任务一:——爬取MTime影评信息:

随便打开一个电影的URLhttp://movie.mtime.com/99547/

查看源代码并找不到票房的字样:

 

 

因此可断定该内容是使用Ajax异步加载生成的。

 

为了进行确认哪些参数是会变化的,再打开一个新的电影的URL并进行相同的操作进行查看:

 

可以直接看到,只有以上三个参数的值是不一样的,其余的都是相同的。其中Ajax_RequestUrl参数值为当前movieURLt的值为当前时间,Ajax_CallBackArgument0的值为当前电影的序号、即其URL中后面的数字。

 

因此就可以构造Ajax请求的URL来爬取数据,回到top 100的主页http://www.mtime.com/top/movie/top100/,分析其中的标签等然后编写代码遍历top 100所有的电影相关票房和影评信息,注意的是并不是所有的电影都有票房信息,这里需要判断即可。

 

代码如下:

 

#coding=utf-8

import requests

import re

import time

import json

from bs4 import BeautifulSoup as BS

import sys

reload(sys)

sys.setdefaultencoding('utf8')

 

headers = {

'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36',

}

 

def Get_Movie_URL():

urls = []

for i in range(1,11):

# 第一页的URL是不一样的,需要另外进行处理

if i != 1:

url = "http://www.mtime.com/top/movie/top100/index-%d.html" % i

else:

url = "http://www.mtime.com/top/movie/top100/"

r = requests.get(url=url,headers=headers)

soup = BS(r.text,'lxml')

movies = soup.find_all(name='a',attrs={'target':'_blank','href':re.compile('http://movie.mtime.com/(\d+)/'),'class':not None})

for m in movies:

urls.append(m.get('href'))

return urls

 

def Create_Ajax_URL(url):

movie_id = url.split('/')[-2]

t = time.strftime("%Y%m%d%H%M%S0368", time.localtime())

ajax_url = "http://service.library.mtime.com/Movie.api?Ajax_CallBack=true&Ajax_CallBackType=Mtime.Library.Services&Ajax_CallBackMethod=GetMovieOverviewRating&Ajax_CrossDomain=1&Ajax_RequestUrl=%s&t=%s&Ajax_CallBackArgument0=%s" % (url,t,movie_id)

return ajax_url

 

def Crawl(ajax_url):

r = requests.get(url=ajax_url,headers=headers)

if r.status_code == 200:

r.encoding = 'utf-8'

result = re.findall(r'=(.*?);',r.text)[0]

if result is not None:

value = json.loads(result)

 

movieTitle = value.get('value').get('movieTitle')

TopListName = value.get('value').get('topList').get('TopListName')

Ranking = value.get('value').get('topList').get('Ranking')

movieRating = value.get('value').get('movieRating')

RatingFinal = movieRating.get('RatingFinal')

RDirectorFinal = movieRating.get('RDirectorFinal')

ROtherFinal = movieRating.get('ROtherFinal')

RPictureFinal = movieRating.get('RPictureFinal')

RStoryFinal = movieRating.get('RStoryFinal')

print movieTitle

if value.get('value').get('boxOffice'):

TotalBoxOffice = value.get('value').get('boxOffice').get('TotalBoxOffice')

TotalBoxOfficeUnit = value.get('value').get('boxOffice').get('TotalBoxOfficeUnit')

print '票房:%s%s' % (TotalBoxOffice,TotalBoxOfficeUnit)

print '%s——No.%s' % (TopListName,Ranking)

print '综合评分:%s 导演评分:%s 画面评分:%s 故事评分:%s 音乐评分:%s' %(RatingFinal,RDirectorFinal,RPictureFinal,RStoryFinal,ROtherFinal)

print '****' * 20

 

def main():

urls = Get_Movie_URL()

for u in urls:

Crawl(Create_Ajax_URL(u))

 

# 问题所在,请求如下单个电影链接时时不时会爬取不到数据

# Crawl(Create_Ajax_URL('http://movie.mtime.com/98604/'))

 

if __name__ == '__main__':

main()

 

运行结果为:

 

 

任务二:爬取肯德基门店信息:

以肯德基的餐厅地址为例:http://www.kfc.com.cn/kfccda/storelist/index.aspx

 

 

可以看到当前城市显示的是广州。

查看页面源代码:

 

 

发现在“当前城市”之后只有“上海”的字样而没有广州,而且城市是通过JS加载进来的,即该页面使用了动态加载技术。

 

FireBug中查看JS相应的请求内容:

 

 

可以看到其中一个JS请求是用于获取城市地址的,将该URL记下用于后面的地址的自动获取然后再解析Json格式的数据即可。

 

 

获取了city信息,就应该是获取所在city的门店信息了,到XHR中查看到如下请求:

 

其为POST请求,提交的内容为city信息等,且返回的响应内容就是含有门店信息的Json格式的内容。

 

因此记录下该POST请求的URL和参数名,其中cname参数为city的值、直接从上一个Ajax请求中获取即可,pageIndex参数是指定第几页(注意门店的换页操作也是使用Ajax加载的),pageSize参数指定每页显示几家店铺、这里为默认的10

代码如下:

 

#coding=utf-8

import requests

import re

import json

 

url = 'http://www.kfc.com.cn/kfccda/storelist/index.aspx'

ajax_url = 'http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js'

store_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'

 

r = requests.get(ajax_url)

result = re.findall(r'=(.*?);',r.text)[0]

value = json.loads(result)

city = value.get('city')

 

for i in range(1,11):

data = {

'cname':city,

'pageIndex':str(i),

'pageSize':'10',

'pid':''

}

r2 = requests.post(url=store_url,data=data)

result2 = json.loads(r2.text)

tables = result2.get('Table1')

for t in tables:

print t.get('storeName')

print t.get('addressDetail')

print '**' * 20

运行结果:

 

实验六:综合案例

实验目的:制作链家网站小区数据爬取

猫眼网站电影数据爬取(直接)

实验设备计算机、windows7、Python、Jupyter

实验课时2课时

实验地点专业机房

实验内容:

任务一:链家网站小区数据爬取

1、 网站解析利用 chrome 查看网页源码,分析“链家”网站网页结构。

1) 打开“链家”网站https://cs.lianjia.com/xiaoqu/cro21/,在网页中右键点击检查,或者 F12 快捷键,查看元素页面; 

2) 检查网站:浏览网站源码查看所需内容。

2Python 语言编写爬虫代码, “链家”网站中爬取长沙指定数据项,数据项包括:区域(雨花、岳麓、天心、开福、芙蓉、望城、宁乡、浏阳、长沙县)、小区名称、参考均价、90天成交数、当前出租数、当前在售数、建成年份、地址。每个区域的数据爬取10页。

3、将爬取的数据保存为csv类型的文件中。 

#get 链家二手房信息

# import requests #比较好用

# res = requests.get('https://bafdidu.com.cn')

# res.raise_for_status()

import requests,lxml,os

from bs4 import BeautifulSoup

header = {

    "Host": 'bj.lianjia.com',

    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400"}

def get_url(url):

    #params是该对象的一个成员变量,是一个数组 getRequest()返回一个对象

    res=requests.get(url,headers=header)   #res=requests.Request(url,headers='',)

    # res.raise_for_status()   #   =print(res.ok)

    # print(res.text)

    #~~~~~~~~~出错返回错误码

    if res.status_code==200:

        # print(res.text)

        return res.text  #没有保存

    else:

        print(url,header)

        return print(res.status_code)

    # res.encoding='utf-8'  #指定编码

    # print(res.status_code)  #返回代码

 

    #——————————

    # f = open('Lianjia.html', 'wb')

    # for chunk in res.iter_content(100000):

    #     f.write(chunk)   #100000  #78981

    # f.close()

    # pass

def get_all_url(html):

    soup=BeautifulSoup(html,'lxml')

    title=soup.select('div.info.clear .title a')  #一种方式

    # href=title[5].get('href')

    #另外一种方式,点进去 获取里面的内容

    # print(href)

    all_url=[]

    for i in title:

        href = i.get('href')

        all_url.append(href)

    return all_url

# return passar_html(html)

 

def parser_info(info_html):

    soup=BeautifulSoup(info_html,'lxml')

    title = soup.select('.title .main')[0].text #名字】

    total = soup.select('span.total')# 售价

    pv = soup.select('.unitPriceValue')# 每平米  1

    name = soup.select('a.info')# 小区名字

    base = soup.select('.base .content')# 基本属性

    transaction = soup.select('.transaction .content')# 交易总属性

    l_trans=soup.select('.transaction .content li')# 8中分类属性

    # l_t=

    # print((l_trans[6].text).split()[0],(l_trans[6].text).split()[1])

    # print(l_trans[0].text,l_trans[1].text)

    # print(title,type(title))

#TODO:JOIN方法使用。及daf 数据传输 .spli()  #'抵押信息    无抵押

    data= ', '.join([

        title,

        total[0].text+"",

        pv[0].text,

        name[0].text,

        str(base[0].text).strip()+'\n',

        l_trans[0].text.strip()+'\n',

        l_trans[1].text.strip()+'\n',

        l_trans[2].text.strip()+'\n',

        l_trans[3].text.strip()+'\n',

        l_trans[4].text.strip()+'\n',

        (l_trans[5].text).strip()+'\n',

        (l_trans[6].text).split()[0]+'\n',

        (l_trans[6].text).split()[1]+'\n',

        l_trans[7].text.strip()+'\n'+'\n'

        #transaction[0].text

     ])

    # print(data)

    return data

def save_f(data):

    f=open('Lian_info.txt','a',encoding='GBK')

    f.write(data)

# data:    iter_content erro

def main(url):

    pass

if __name__=='__main__':

    url='https://bj.lianjia.com/ershoufang/'

html=get_url(url)

   get_url(url)

    all_urls=get_all_url(html)

    # print(all_urls)

    #所有的URL调用GEt方法

    for url in all_urls:

        info_html=get_url(url)

        parser_info(info_html)

        data = parser_info(info_html)

 

        save_f(data)

        # print(info_html)

    main(url)

 


任务二:猫眼网站电影数据爬取(直接)

1、 网站解析利用 chrome 查看网页源码,分析“猫眼”网站网页结构。

1) 打开“猫眼”网站https://maoyan.com/films?showType=3&offset=30,在网页中右键点击检查,或者 F12 快捷键,查看元素页面; 

2) 检查网站:浏览网站源码查看所需内容。

2Python 语言编写爬虫代码, “猫眼”网站中爬取指定数据项,数据项包括:电影名、评分、类型、国家、上映时间、票房。每个类型的电影数据爬取10页。

3、将爬取的数据保存为csv类型的文件中。 

程序具体如下:

1、首先打开猫眼专业版-实时票房 其网址为:https://piaofang.maoyan.com/dashboard,可以看见现在的实时电影票房数据,可以看见 “今日实时” 的数据在不断地动态增加:

 

该页面可能使用了Ajax(即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML))技术.

2、利用浏览器的开发者工具进行分析:我们可以发现每隔一段时间都会有一个新的请求,其请求类型都为xhr,而Ajax的请求类型就是xhr,这请求可能就是实时更新的票房信息,而我们需要的数据可能就在这些文件里,于是我们选择一个进行分析:

3、获得获取到该请求的链接,接下来我们就用Python模拟该请求:

 

headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko)Chrome/68.0.3440.106 Safari/537.36' } 

def get_html(): 

''' 获取JSON文件  :return: JSON格式的数据     '''   

#请求second.json的URL 

url = 'https://box.maoyan.com/promovie/api/box/second.json'     

try:         

response = requests.get(url, headers=headers)         

if response.status_code == 200:             

#由于是JSON文件,我们可以返回JSON格式的数据便于后续提取 

return response.json()         

else:   

 return -1     

except:         

return None

  获取对应的JSON数据后,我们就可以利用进行提取操作了。

def parse_infor(json):     

   '''从JSON数据中提取电影票房数据,包括:电影名,上映信息,综合票房,票房占比,累计票房 :param json: JSON格式的数据  :return: 每次循环返回一次字典类型的电影数据   '''     

if json:         

# 利用json中的get()方法层层获取对应的信息 

items = json.get('data').get('list')  

for item in items: 

piaofang = {}

piaofang['电影名'] = item.get('movieName')             

piaofang['上映信息'] = item.get('releaseInfo')  

piaofang['综合票房'] = item.get('boxInfo')             

piaofang['票房占比'] = item.get('boxRate')             

piaofang['累计票房'] = item.get('sumBoxInfo')     

# 利用生成器每次循环都返回一个数据             

yield piaofang     

else:         

return None

  读者可能看见我们没有使用常规的return进行函数返回,而是使用了生成器,这样就能每次循环都返回一次数据,具体读者可以进一步了解学习,接下来我们就将提取好的票房信息存储为格式化的HTML文件:

def save_infor(results):     

'''  存储格式化的电影票房数据HTML文件     

:param results: 电影票房数据的生成器  

:return: None     '''     

rows = '' 

for piaofang in results:         

# 利用Python中的format字符串填充html表格中的内容         

row = '<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>'.format(piaofang['电影名'], piaofang['上映信息'], piaofang['综合票房'],piaofang['票房占比'], piaofang['累计票房']) 

 # 利用字符串拼接循环存储每个格式化的电影票房信息   

 rows = rows + '\n' + row     

# 利用字符串拼接处格式化的HTML页面     

piaofang_html = ''' <!DOCTYPE html> <html> <head>     <meta charset="UTF-8"> <title>电影票房</title> </head> <body> <style> 

.table1_5 table { width:100%;  margin:15px 0  } 

.table1_5 th {background-color:#00BFFF;  color:#FFFFFF }     

.table1_5,.table1_5 th,.table1_5 td { font-size:0.95em; text-align:center; padding:4px;  border:1px solid #dddddd; border-collapse:collapse }   .table1_5 tr:nth-child(odd){  background-color:#aae9fe;  }     

.table1_5 tr:nth-child(even){ background-color:#fdfdfd;}  

</style> <table class='table1_5'><tr> <th>电影名</th><th>上映信息</th> <th>综合票房</th>  <th>票房占比</th><th>累计票房</th> </tr> ''' + rows + ''' </table> </body> </html> '''    

 # 存储已经格式化的html页面     

with open('piaofang.html', 'w', encoding='utf-8') as f:

   f.write(piaofang_html)

  我们将以上过程整合,即可得到完整的票房数据获取的代码实例:

import requests 

headers = {  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' } 

def get_html(): 

 ''' 获取JSON文件:return: JSON格式的数据  '''     

# 请求second.json的URL  

url = 'https://box.maoyan.com/promovie/api/box/second.json'     

try:         

response = requests.get(url, headers=headers)         

if response.status_code == 200:             

# 由于是JSON文件,我们可以返回JSON格式的数据便于后续提取  

return response.json()         

else:             

return -1     

except:         

return None 

def parse_infor(json):     

'''  从JSON数据中提取电影票房数据,包括:电影名,上映信息,综合票房,票房占比,累计票房 :param json: JSON格式的数据  :return: 每次循环返回一次字典类型的电影数据 '''     

if json:         

# 利用json中的get()方法层层获取对应的信息   

items = json.get('data').get('list')         

for item in items:             

piaofang = {}             

piaofang['电影名'] = item.get('movieName') 

piaofang['上映信息'] = item.get('releaseInfo')  

piaofang['综合票房'] = item.get('boxInfo')

piaofang['票房占比'] = item.get('boxRate')

piaofang['累计票房'] = item.get('sumBoxInfo') 

# 利用生成器每次循环都返回一个数据             

yield piaofang     

else:         

return None 

def save_infor(results):     

'''     存储格式化的电影票房数据HTML文件     

:param results: 电影票房数据的生成器     

:return: None     '''     

rows = ''    

 for piaofang in results:         

# 利用Python中的format字符串填充html表格中的内容         

row = '<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>'.format(piaofang['电影名'], piaofang['上映信息'],  piaofang['综合票房'],  piaofang['票房占比'], piaofang['累计票房'])         

# 利用字符串拼接循环存储每个格式化的电影票房信息         

rows = rows + '\n' + row     

# 利用字符串拼接处格式化的HTML页面     

piaofang_html = ''' <!DOCTYPE html> <html> <head>     <meta charset="UTF-8"> <title>电影票房</title> </head> <body> <style> 

.table1_5 table {  width:100%;  margin:15px 0   }     

.table1_5 th { background-color:#00BFFF;  color:#FFFFFF  }   

.table1_5,.table1_5 th,.table1_5 td {  font-size:0.95em;         text-align:center; padding:4px; border:1px solid #dddddd;         border-collapse:collapse }    

 .table1_5 tr:nth-child(odd){  background-color:#aae9fe;     }     .table1_5 tr:nth-child(even){  background-color:#fdfdfd;     }     </style> <table class='table1_5'> <tr> <th>电影名</th> <th>上映信息</th><th>综合票房</th><th>票房占比</th> <th>累计票房</th> </tr> ''' + rows + '''</table> </body> </html> '''     

# 存储已经格式化的html页面     

with open('piaofang.html', 'w', encoding='utf-8') as f:         

f.write(piaofang_html) 

if __name__ == "__main__":     

# 获取信息     

json = get_html()     

# 提取信息     

results = parse_infor(json)     

# 存储信息     

save_infor(results)

HTML文件存储效果如下图所示:  

  
  可以看见,动态网页的爬虫可能会更加简单些,关键就在于找到对应的XHR格式的请求,而一般这种格式的文件都是JSON格式的,提取相对也会更加简单方便,而读者可能会问为何要把这个信息存储为HTML文件格式的呢,喜欢电影的读者可能会经常打开猫眼电影查看每天的电影票房数据,何不尝试将我们所学的爬虫知识运用起来制作一个定时爬取电影票房数据并推送至个人邮箱的爬虫小程序呢,这样就省得我们每天打开网页查看,让数据主动为我们服务,也算是学习致用了吧,感兴趣的读者可以自己尝试下,下图笔者根据这个爬虫程序扩展每天收到的实时票房信息邮件,每天定时爬取推送给笔者,列表内容如下图所示:   推动内容如下图所:

核发:nclgjsj 点击数:543收藏本页