2024数据采集与融合技术实践-作业1

news/2024/10/20 19:44:29

作业①

要求:用requests和BeautifulSoup库方法定向爬取给定网址(http://www.shanghairanking.cn/rankings/bcur/2020)的数据,屏幕打印爬取的大学排名信息。

代码与运行结果

代码:

#导入所需要的库
import requests
from bs4 import BeautifulSoup
import pandas as pd#爬取网址的网址
url = "https://www.shanghairanking.cn/rankings/bcur/2024"
#发送请求
response = requests.get(url)
#设置编码格式
response.encoding = 'utf-8'
#获取相应内容
html = response.text#定义存储形式为字典
all = {"school": {}, "province": {}, "type": {}, "score": {}}#定义beautifulSoup对象
soup = BeautifulSoup(html, "html.parser")
#找到内容存储主体部分
body = soup.find(attrs={"class": "rk-table"}).find("tbody").find_all("tr")#定义获取到的信息在all中的存储位置
count = 0#按排名顺序遍历主体部分,获取到每一个大学信息的信息存储容器
for info in body:# 获取学校名字school_names = soup.find_all("span", attrs={"class": "name-cn"})# 处理数据并保存name_count = 0for name in school_names:all["school"][name_count] = name.text.strip().replace(" ", "").replace("\n", "")name_count += 1#因为省份等信息存储在td中,所以通过寻找td来解析获取到的数据td = info.find_all("td")province = td[2].text.strip().replace(" ", "").replace("\n", "")all["province"][count] = provincetype_ = td[3].text.strip().replace(" ", "").replace("\n", "")all["type"][count] = type_score = td[4].text.strip().replace(" ", "").replace("\n", "")all["score"][count] = score#位置加一,以便后面获取到的信息依次存储count += 1# 将字典转换为 pandas DataFrame
df = pd.DataFrame({'排名': range(1, len(all['school']) + 1),'学校名字': [all['school'][i] for i in range(len(all['school']))],'省市': [all['province'][i] for i in range(len(all['province']))],'学校类型': [all['type'][i] for i in range(len(all['type']))],'总分': [all['score'][i] for i in range(len(all['score']))]
})# 显示转换后的 DataFrame,index=False是取消原来的dataframe自动编号
print(df.to_string(index=False))# 如果需要,可以将其保存为 CSV 文件
# df.to_csv('school_ranking.csv', index=False, encoding='utf-8')

运行结果:

命令行输出:

jupyter输出:

心得体会

通过这种直接给网页发送请求获取网页数据的方式还是比较简单的,数据直接存储在网页结构里面,主要是对网页解析部分,有些返回的数据会参杂着没有用的字符,如空格换行符等,这个时候就需要再次解析才能过滤获得想要的数据。最后采用了DataFrame的形式展现数据,一个是能使数据排列整齐,一个是存储到DataFrame中能更好的用做数据分析。

对于requests库的使用,该库集成了很多功能,能使代码编写更加简单,使我们高效的编写代码与调试代码;对于BeautifulSoup的使用,该库对于元素的解析非常高效,语法简洁明了,但是对于细节处理部分稍微会差一点,因为该库只能检索标签,没有很好的能将text值多余部分消除。

作业②

要求:用requests和re库方法设计某个商城(自已选择)商品比价定向爬虫,爬取该商城,以关键词“书包”搜索页面的数据,爬取商品名称和价格。

代码与运行结果

代码:

import requests  # 用于发送HTTP请求
import re  # 正则表达式模块,用于匹配字符串模式
import threading  # 线程模块,用于并发下载图片
import time  # 时间模块,用于暂停程序的执行
import random  # 随机模块,用于生成随机数
import os  # 操作系统模块,用于文件操作# 模拟浏览器登录,定义一个User-Agent,伪装请求为浏览器发出的
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0"# 定义cookie字符串,用于保持会话状态,模拟登录后的请求
cookie = "__jdu=17271449574151433017795; shshshfpa=ded88cf8-09ce-a477-ebe4-2493c67e8e78-1727144962; shshshfpx=ded88cf8-09ce-a477-ebe4-2493c67e8e78-1727144962; TrackID=13Pn2WnjRYPpif5576bxpXfg2LgdzJBvmBmxNDVlnjcS2PW7g12CEUt-Weeae7DJvs5YXD72sNwIeo07aE67NLntR3j7K6iiAOvC6d98uS7z43bHiiT8DSitPopoziGmu; thor=715141BE6C9536F17D1864B0AB49B027336956B4A93B43087E32EF1A158B0017B8955B71BC4CC9CDDF3603CA60C4A03365163B28FFC27EEE0597B416E5DCC1412E994C9E0A9F1C656ACFCD63CD64EB06BE1436FF223EBEA4D2940AAF7BF457B4964FD83E5B9723D347C0E642ECE4A7C11952DC98A41773BB0CC93B344004403895112E7460413D45066A56C24A62751FE4F6B20901534C5193B63C175FAC1CEC; light_key=AASBKE7rOxgWQziEhC_QY6yalHIWSMfjmMdQCIfmiiLp90g34uoBR2WngQeQmaR45Rno5KRb; pinId=t8vUk2ONJqfeMhHAdNEcfA; pin=jd_IMrvTjYrsOYY; unick=jd_i8b81qc9y0r86f; _tp=QPV29p3JH9DfoHpsRIj1wQ%3D%3D; _pst=jd_IMrvTjYrsOYY; qrsc=3; ipLoc-djd=16-1303-1305-48927; __jdv=76161171|cn.bing.com|-|referral|-|1728467486377; shshshfpb=BApXSqce5c_dALiLo-4lKw1ktTeR9uD-iBmVVTk1r9xJ1Mr4f74C2; 3AB9D23F7A4B3C9B=4VJNECADUFJ4BVR3NKQPF75TI2MLCZHTQQCGPYAFMQD33EJ6JXO6INMPS7JUYEUTFXHXKPAQTXWRV5Y2ZPWFC4TFIQ; __jda=76161171.17271449574151433017795.1727144957.1728467486.1729399437.8; __jdb=76161171.1.17271449574151433017795|8.1729399437; __jdc=76161171; 3AB9D23F7A4B3CSS=jdd034VJNECADUFJ4BVR3NKQPF75TI2MLCZHTQQCGPYAFMQD33EJ6JXO6INMPS7JUYEUTFXHXKPAQTXWRV5Y2ZPWFC4TFIQAAAAMSVA6VL3IAAAAADPNSJBEFDTSPL4X; _gia_d=1; flash=3_0b5lq6EleaKtOFGosYp8NM4saVZ87rUzmUmVT9RA5qPOvwuy9Rc7RHOjHgX_QOiTXb5rjB0soP8FSHLMo6Wen1vJjjDuy46ML7P9uXntJgprrRSLdPy9aiA_EPUXLDy2lmtbqLKf4BedJz0rurzL-ZxYCfvD42Muko84jAG3bKeRvcuLcLry; PCSYCityID=CN_350000_350100_0; jsavif=1; jsavif=1; xapieid=jdd034VJNECADUFJ4BVR3NKQPF75TI2MLCZHTQQCGPYAFMQD33EJ6JXO6INMPS7JUYEUTFXHXKPAQTXWRV5Y2ZPWFC4TFIQAAAAMSVA6VL3IAAAAADPNSJBEFDTSPL4X"# 将User-Agent和Cookie信息存储在headers中,作为请求头发送
headers = {"user-agent": user_agent, "cookie": cookie}# 定义获取图片函数,参数n代表要爬取的页数
def getPic(n):global threads  # 使用全局变量threads来保存所有启动的线程count = 0  # 用于记录图片的编号# 循环遍历每一页for page in range(1, n + 1):url = f"https://search.jd.com/Search?keyword=%E4%B9%A6%E5%8C%85&page={page}"  # 构建请求URL,模拟搜索“书包”# 使用requests库发起HTTP GET请求try:response = requests.get(url, headers=headers, timeout=10)  # 发送请求,超时设置为10秒response.raise_for_status()  # 如果请求失败,抛出HTTPError异常html = response.text  # 获取页面HTML内容except requests.RequestException as e:print(f"Failed to retrieve page {page}: {e}")  # 请求出错时,打印错误信息并跳过当前页continue# 使用正则表达式匹配每一个商品的HTML容器reg_li = r'<li data-sku.*?</li>.*?</div>\n\t</li>'match_li = re.findall(reg_li, html, re.DOTALL)  # 匹配所有<li>标签# 遍历匹配到的商品列表for li in match_li:# 使用正则表达式匹配商品的图片信息reg_pic = "<img w.*?>"match_pic = re.findall(reg_pic, li, re.DOTALL)# 提取图片URLreg_pic_url = 'data-lazy-img="(.*?)"'  # 匹配图片路径if match_pic:  # 如果找到图片信息try:pic_url = "https:" + re.findall(reg_pic_url, match_pic[0])[0]  # 拼接完整的图片URLcount += 1  # 计数器递增# 创建下载线程并启动T = threading.Thread(target=downLoad, args=(pic_url, count))T.setDaemon(False)  # 设置线程为非守护线程,主线程结束前,子线程要完成T.start()  # 启动线程threads.append(T)  # 将线程添加到线程列表except IndexError:print("Failed to find image URL in match_pic.")  # 如果没有找到图片URL,打印错误信息except Exception as e:print(e)  # 打印其他异常# 随机暂停0到3秒,避免频繁请求被封禁time.sleep(random.randint(0, 3))# 定义下载图片的函数
def downLoad(url, title):try:# 使用requests下载图片数据response = requests.get(url, timeout=100)  # 请求图片,设置超时时间为100秒response.raise_for_status()  # 如果请求失败,抛出HTTPError异常data = response.content  # 获取图片的二进制数据# 检查保存图片的文件夹是否存在,如果不存在则创建if not os.path.exists("./jingdong"):os.makedirs("./jingdong")# 生成图片保存路径downLoadPath = f"./jingdong/{str(title)}.jpg"# 将图片数据写入文件with open(downLoadPath, "wb") as fobj:fobj.write(data)except requests.RequestException as e:print(f"Failed to download {url}: {e}")  # 如果下载失败,打印错误信息except Exception as e:print(e)  # 打印其他异常# 初始化线程列表,用于保存所有的线程对象
threads = []# 启动获取图片的函数,参数为要爬取的页数
getPic(2)# 等待所有线程执行完毕
for t in threads:t.join()  # 阻塞主线程,等待子线程执行完毕print("The End")  # 打印结束标志

运行结果:

心得体会

使用多线程对京东的图片进行爬取,将网页解析与图片下载过程分开,大大的提高了下载效率。而后面所加入的线程阻塞,能大大的提高图片下载的成功率,可以看到本次试验是爬取两页图片,每页有30张图片,总共爬取到了60张图片,没有多线程的加持成功率大概只有百分之五十。当然加入多线程并不一定会将成功率提到百分百,借用淘宝图片爬取的例子,其单线程到多线程的成功率只能从大约百分之五十提到七八十。

作业③:

要求:爬取一个给定网页( https://news.fzu.edu.cn/yxfd.htm)或者自选网页的所有JPEG和JPG格式文件

代码与运行结果

代码:

from bs4 import BeautifulSoup  # 导入BeautifulSoup库,用于解析HTML文档
import requests  # 导入requests库,用于发送HTTP请求
import os  # 导入os模块,用于文件操作# 定义下载图片的函数
def downLoad(url, title):try:# 使用requests库发送HTTP GET请求,下载图片response = requests.get(url, timeout=100)  # 设置请求超时为100秒response.raise_for_status()  # 如果请求不成功,抛出异常data = response.content  # 获取图片的二进制数据# 检查保存图片的目录是否存在,如果不存在则创建if not os.path.exists("./fzu"):os.makedirs("./fzu")# 定义图片保存路径,命名为"title.jpg"downLoadPath = f"./fzu/{str(title)}.jpg"# 将下载的图片数据写入文件with open(downLoadPath, "wb") as fobj:fobj.write(data)except requests.RequestException as e:print(f"Failed to download {url}: {e}")  # 捕获请求异常,打印错误信息except Exception as e:print(e)  # 捕获其他异常并打印# 要爬取的福州大学新闻网站URL
url = "https://news.fzu.edu.cn/yxfd.htm"# 使用requests库发送HTTP GET请求获取网页内容
response = requests.get(url, timeout=10)  # 设置请求超时为10秒
response.raise_for_status()  # 如果请求失败,抛出异常
html = response.text  # 获取页面的HTML内容# 使用BeautifulSoup解析HTML文档
bs = BeautifulSoup(html, "html.parser")# 查找页面中所有的<img>标签,获取图片的相关信息
img_url = bs.select("img")  # 使用CSS选择器获取所有图片标签# 定义一个列表来保存所有jpg和jpeg格式的图片URL
img_jpg_or_jpeg = []# 遍历找到的所有图片URL
for url in img_url:# 筛选出后缀为jpg或jpeg的图片if url["src"][-3:] == "jpg" or url["src"][-4:] == "jpeg":# 补全相对路径为完整URLnew_url = "https://news.fzu.edu.cn" + url["src"]# 将符合条件的图片URL添加到列表中img_jpg_or_jpeg.append(new_url)# 初始化计数器,用于命名下载的图片
count = 1# 遍历筛选出的图片URL列表,下载每一张图片
for url in img_jpg_or_jpeg:# 调用下载函数downLoad,传入图片URL和计数器作为图片名称downLoad(url, count)count = count + 1  # 计数器递增,用于为下一张图片命名

运行结果:

心得体会

因为该任务的爬取数量不是很多,就没有用前面的那种多线程,如果爬取的图片比较多的话改为和前面的多线程一样即可。但是这里有要求是要爬取JPG或者JPEG格式的图片,在后面加个判断后缀名即可,可以看到原来的网站的很多PNG图片都被过滤掉了,只剩下了最后的3张符合要求的图片。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/73916.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

【报告】务虚笔记

务虚笔记同学们大家好,接下来由我向大家推荐史铁生的《务虚笔记》 我的报告分为四部分。书籍简介首先是书籍简介。务虚笔记是史铁生先生的首部长篇小说,于1996年发表在《收获》杂志上。它的行文优美、凝练,情感真挚、厚重,语言平实易读,虽然理解它的内容会让第一次读此书的…

高级程序设计第三次作业

这个作业属于哪个课程:https://edu.cnblogs.com/campus/fzu/2024C 这个作业要求在哪里:https://edu.cnblogs.com/campus/fzu/2024C/homework/13284 学号:102300107 姓名:陈沁怡 4.8.2感想:学会了转义字符的使用 4.8.3感想:数字表达的转换 4.8.44.8.64.8.7理解lf和f之间的…

2024-2025-1 20241322 《计算机基础与程序设计》第四周学习总结

2024-2025-1 20241322 《计算机基础与程序设计》第四周学习总结 作业信息这个作业属于哪个课程 https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP这个作业要求在哪里 https://www.cnblogs.com/rocedu/p/9577842.html#WEEK04这个作业的目标 <门电路 组合电路,逻辑电路…

http://192.168.14.232/contest/59

A:创历史新低 dalao:d<=5,所以一个位置上只能是[i-d,i+d],考虑状压 ljxs code #include <bits/stdc++.h> using namespace std; const int maxn=505; const int mod=998244353; int read(){int ret=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch==-)f=-f;ch=ge…

文件的物理结构

文件块和磁盘块 类似于内存分页,磁盘中的存储单元也会被分为一个个“块/磁盘块/物理块”。很多操作系统中,磁盘块的大小与内存块、页面的大小相同。内存与磁盘之间的数据交换(即读/写操作、磁盘I/O)都是以“块”为单位进行的。即每次读入一块,或每次写出一块文件分配方式 连…

2024-2025-1 20241307《计算机基础与程序设计》第四周学习总结

作业信息这个作业属于哪个课程 (2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 (2024-2025-1计算机基础与程序设计第四周作业)这个作业的目标作业正文 (2024-2025-1 学号20241307《计算机基础与程序设计》第四周学习总结)教材学习内容总结第二章主要介绍了二进制数…

第38篇 net8接口调试方式

.net提供了内置的接口调试方式 1.新建.net core web api控制台应用程序 2.封装好jwt验证机制 token令牌验证机制/// <summary>/// 登录/// </summary>/// <param name="request"></param>/// <returns></returns>/// <except…

使用MySQL之用正则表达式进行搜索

1. 正则表达式介绍 正则表达式是用来匹配文本的特殊的串(字符集合)。 如果你想从一个文本文件中提取电话号码,可以使用正则表达式。 如果你需要查找名字中间有数字的所有文件,可以使用一个正则表达式。 如果你想在一个文本块中找到所有重复的单词,可以使用一个正则表达式。…