数据采集第一次作业(2022)

作业1:

题目:要求用urllib和re库方法定向爬取给定网址2020中国最好学科排名的数据。输出信息如下:

2020排名 全部层次 学校类型 总分
1 前2% 中国人民大学 1069.0
2 ... ...   ...

 

 

解题:

url="https://www.shanghairanking.cn/rankings/bcsr/2020/0812"
headers={"User-Agent":"Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre"}
req=urllib.request.Request(url,headers=headers)
data=urllib.request.urlopen(req)# 发送请求
soup=data.read().decode('utf-8')# 解析网页

 1.2根据网页结点信息构造正则表达式

 rank=[]
    level=[]
    school=[]
    score=[]
    for items in re.findall(r'<tr data-v-68e330ae>.*?</tr>', soup, re.S|re.M):
        for a in re.findall(r'<div class="ranking".*?>(.*?)</div>',items,re.S|re.M):
            rank.append(int(a)) #记录排名
            
        for b in re.findall(r'<td data-v-68e330ae.*?>(.*?)</td>',items,re.S|re.M):
            for k in re.findall(r'(.*?)<!---->',b,re.S):
                level.append(k.strip()) #记录层次
            for k in re.findall(r'\d+\.\d',b,re.S):
                score.append(k.strip()) #记录总分
                
        for c in re.findall(r'<a .*?name-cn.*?>(.*?)</a>', items, re.S|re.M):
            school.append(c)# 记录学校

  1.3输出代码

    tplt = "{0:^10}\t{1:{4}<10}\t{2:<10}\t{3:<10}"
    print(tplt.format("2020排名", "全部层次", "学校名称", "总分", chr(12288)))
    for i in range(len(rank)):
        print(tplt.format(rank[i],level[i],school[i],score[i],chr(12288)))
    #中英文混排时采用chr(12288)

1.4输出结果

 

 

作业2:

要求:用requests和Beautiful Soup库方法设计爬取https://datacenter.mee.gov.cn/aqiweb2/ AQI实时报。

输出信息:

序号 城市 AQI PM2.5 .. .. .. ..
1 北京 ... ...        
               

 

 

 

 

 

 

解题

获取http

使用requests进行Get请求:

url = "https://datacenter.mee.gov.cn/aqiweb2/"
response = requests.get(url)
html = response.text
# 使用缓存,防止被ban
# with open('./.cache/aqiweb2.html', 'r', encoding='utf-8') as f:
#     html = f.read()

 同上,添加一个缓存。

构建soup,解析表格

这里需要先解析下图中选中部分的表格:

 

使用Beatiful Soup进行解析:

# 构建soup对象
soup = BeautifulSoup(html, "lxml")

# 解析表格
table = soup.find('div', attrs={"id": "demo"}).table.tbody

提取数据

 

查看该表格,发现该tbody内,tr均匀排列,且各个tr内的td内容即为需要的数据(即td.text):

因此,只需要进行两层遍历,就能提取出所有信息:

i = 0
for tr in table.find_all('tr'):
    print("{:^6}".format(i), end='\t')
    for td in tr.find_all('td'):
        print("{:^6}".format(strQ2B(clear_data(td.text))), end='\t')
    print()
    i += 1

 2、运行结果

 

3、文件地址:https://gitee.com/mirrolied/spider_test/blob/master/lesson_2/session_2.py

作业3

要求:使用urllib和requests爬取(https://news.fzu.edu.cn/),并爬取该网站下的所有图片输出信息:将网页内的所有图片文件保存在一个文件夹中

解题

获取html

由于该题要求使用urllib.request和requests进行爬取,索性将两种方法结合缓存(即读取本地文件)整合成一个函数,由用户选择请求方法。

  构建一个get_html函数,输入url以及请求方法,返回html文本:

def get_html(url: str, request_type: str) -> str:
    """
    获取html
    :param url: 访问地址
    :param request_type: 请求方式:  urllib.request 或 urllib.request 或相应缓存
    :return: html
    """
    if request_type == "urllib.request":
        # urllib.request
        return urllib.request.urlopen(url).read().decode("utf-8")
    elif request_type == "requests":
        # requests
        response = requests.get(url)
        return response.text
    else:
        # 读取缓存文件
        with open(f'./.cache/{request_type}.html', 'r', encoding='utf-8') as f:
            return f.read()

 解析图片

使用正则匹配的方式,将所有的<img>标签内的src提取出来:

imgList = re.findall(r'<img.*?src="(.*?)"', html, re.S)

 

图片保存

文件内容即请求图片url返回内容,使用with open创建文件管理对象,并将模式设置为wb(二进制写入模式):

resp = requests.get(img_url)
with open(f'./download/{img.split("/")[-1]}', 'wb') as f:
    f.write(resp.content)

 使用字符串分割从url中提取出文件的名称(保证后缀名无误):

    img.split("/")[-1]
  或以"."进行分割,仅提取后缀名,自己对文件进行标号命名。

  最后使用f.write(resp.content)即可实现保存。

def get_imgs(html:str, download=True) -> None:
    """
    获取所有图片地址,可选择下载
    :param html: 输入html
    :param download: 是否下载
    :return: None
    """
    imgList = re.findall(r'<img.*?src="(.*?)"', html, re.S)
    print(imgList)
    print(f'共有{len(imgList)}张图片')
    if download:
        for i, img in enumerate(imgList):
            img_url = "http://news.fzu.edu.cn" + img
            print(f"正在保存第{i + 1}张图片 路径:{img_url}")
            resp = requests.get(img_url)
            with open(f'./download/{img.split("/")[-1]}', 'wb') as f:
                f.write(resp.content)

复制代码

 运行结果

 

本次作业gitee地址:https://gitee.com/mirrolied/spider_test/tree/master/lesson_1

 

posted @ 2020-10-03 10:33  ハレハレヤ  阅读(86)  评论(0编辑  收藏  举报