第二次作业报告
一、作业内容概述
在本次作业中,我完成了以下三个任务:
- 作业①:从中国气象网(http://www.weather.com.cn)爬取指定城市的7日天气预报,并将数据保存至数据库。
- 作业②:使用
requests
和BeautifulSoup
库定向爬取股票相关信息,并存储在数据库中。 - 作业③:爬取中国大学2021主榜(https://www.shanghairanking.cn/rankings/bcur/2021)的所有院校信息,并将数据保存至数据库,同时录制并展示浏览器F12调试过程的Gif。
以下是各项作业的详细实现过程和心得体会。
1. 作业①:爬取中国气象网7日天气预报
实现代码
import urllib.request
import sqlite3
from bs4 import BeautifulSoup
from bs4 import UnicodeDammit
class WeatherDB:
#打开数据库
def openDB(self):
self.con=sqlite3.connect("weathers.db")
self.cursor=self.con.cursor()
try:
self.cursor.execute("create table weathers (wCity varchar(16),wDate varchar(16),wWeather varchar(64),wTemp varchar(32),constraint pk_weather primary key (wCity,wDate))")
except:
self.cursor.execute("delete from weathers")
#关闭数据库
def closeDB(self):
self.con.commit()
self.con.close()
#插入数据
def insert(self, city, date, weather, temp):
try:
self.cursor.execute("insert into weathers (wCity,wDate,wWeather,wTemp) values (?,?,?,?)",
(city, date, weather, temp))
except Exception as err:
print(err)
#打印数据库
def show(self):
self.cursor.execute("select * from weathers")
rows = self.cursor.fetchall()
print("%-16s%-16s%-32s%-16s" % ("city", "date", "weather", "temp"))
for row in rows:
print("%-16s%-16s%-32s%-16s" % (row[0], row[1], row[2], row[3]))
class WeatherForecast:
def __init__(self):
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre"}
self.cityCode = {"北京": "101010100", "上海": "101020100", "广州": "101280101", "深圳": "101280601"}
def forecastCity(self, city):
if city not in self.cityCode.keys():
print(city + " code cannot be found")
return
url = "http://www.weather.com.cn/weather/" + self.cityCode[city] + ".shtml"
#爬虫
try:
req = urllib.request.Request(url, headers=self.headers)
data = urllib.request.urlopen(req)
data = data.read()
dammit = UnicodeDammit(data, ["utf-8", "gbk"])
data = dammit.unicode_markup
soup = BeautifulSoup(data, "lxml")
lis = soup.select("ul[class='t clearfix'] li")
for li in lis:
try:
date=li.select('h1')[0].text
weather=li.select('p[class="wea"]')[0].text
temp=li.select('p[class="tem"] span')[0].text+"/"+li.select('p[class="tem"] i')[0].text
print(city,date,weather,temp)
self.db.insert(city,date,weather,temp)
except Exception as err:
print(err)
except Exception as err:
print(err)
def process(self, cities):
self.db = WeatherDB()
self.db.openDB()
for city in cities:
self.forecastCity(city)
print("\n")
print("开始输出数据库:\n")
self.db.show()
self.db.closeDB()
WF = WeatherForecast()
WF.process(["北京", "上海", "广州", "深圳"])
print("\n")
print("输出数据库完成")
运行截图
图1:爬取天气预报后的数据库内容截图
心得体会
在完成作业①的过程中,我深入学习了网页数据爬取和数据库操作的相关技术,具体体会如下:
1,类与模块化设计:
WeatherDB 类:负责数据库的连接、操作和关闭,实现了打开数据库、插入数据以及展示数据的功能。这种封装使得数据库操作与爬虫逻辑分离,代码更加清晰和易于维护。
WeatherForecast 类:负责网页数据的抓取和解析。通过将不同城市的天气预报爬取逻辑封装在一个类中,提高了代码的复用性和扩展性。
2,使用 urllib.request 进行网络请求:
尽管 requests 库在现代 Python 开发中更为流行,但通过使用 urllib.request,我理解了更底层的网络请求机制。这对深入理解 HTTP 请求有帮助。
3,处理网页编码:
由于中国气象网使用的是不同的编码格式(如 utf-8 和 gbk),我使用了 BeautifulSoup 的 UnicodeDammit 工具来自动检测和转换编码,确保了网页内容的正确解析。这一过程增强了我处理不同编码网页的能力。
4,HTML 解析与数据提取:
通过分析网页的结构,使用 BeautifulSoup 提取所需的天气信息,如日期、天气描述和温度。掌握了 select 方法和 CSS 选择器的使用,提高了数据提取的效率和准确性。
5,数据操作与异常处理:
使用 SQLite 数据库进行数据存储,实现了数据的持久化管理。通过在数据库操作中加入异常处理,确保了程序的健壮性,避免因重复插入或其他错误导致程序崩溃。
在 WeatherDB 类中,通过设置主键约束(PRIMARY KEY (wCity, wDate)),防止了数据的重复插入,提高了数据库的完整性。
6,日志与调试:
在数据抓取和插入过程中,加入了 print 语句输出当前操作的信息和错误提示,帮助我及时发现和解决问题。这种调试方式在实际开发中非常实用。
7,代码规范与可读性:
遵循 Python 的编程规范,合理使用缩进和注释,使代码结构清晰,易于理解和维护。通过模块化设计和函数封装,提升了代码的可读性和复用性。
8,实际应用与挑战:
在爬取过程中,遇到了网页结构变化和动态内容加载的挑战。通过不断调试和优化选择器,最终成功提取了所需的数据。这让我认识到,网页结构的多变性和复杂性是爬虫开发中常见的问题,必须具备灵活应对的能力。
本次作业虽然实现了基本的功能,但在数据抓取效率和错误处理方面还有提升空间。未来可以考虑引入多线程或异步编程,提高爬取速度;同时,优化异常处理机制,增强程序的鲁棒性。
通过这次作业,我不仅掌握了基本的网页爬取技术和数据库操作,还提升了代码设计和问题解决的能力。这些技能将在我未来的数据处理和分析工作中发挥重要作用。同时,这次实践也让我意识到,理论知识与实际应用相结合的重要性,只有通过不断实践,才能更好地掌握和运用所学知识。
二、作业①:爬取中国气象网7日天气预报
1. 实现代码
在本次作业中,我使用了 Python 的 urllib.request
、BeautifulSoup
库来爬取中国气象网(http://www.weather.com.cn)指定城市的7日天气预报数据,并将其保存到 SQLite 数据库中。以下是我的具体实现代码:
import urllib.request
import sqlite3
from bs4 import BeautifulSoup
from bs4 import UnicodeDammit
class WeatherDB:
# 打开数据库
def openDB(self):
self.con = sqlite3.connect("weathers.db")
self.cursor = self.con.cursor()
try:
self.cursor.execute("""
CREATE TABLE weathers (
wCity VARCHAR(16),
wDate VARCHAR(16),
wWeather VARCHAR(64),
wTemp VARCHAR(32),
CONSTRAINT pk_weather PRIMARY KEY (wCity, wDate)
)
""")
except:
self.cursor.execute("DELETE FROM weathers")
# 关闭数据库
def closeDB(self):
self.con.commit()
self.con.close()
# 插入数据
def insert(self, city, date, weather, temp):
try:
self.cursor.execute("""
INSERT INTO weathers (wCity, wDate, wWeather, wTemp)
VALUES (?, ?, ?, ?)
""", (city, date, weather, temp))
except Exception as err:
print(err)
# 打印数据库
def show(self):
self.cursor.execute("SELECT * FROM weathers")
rows = self.cursor.fetchall()
print("%-16s%-16s%-32s%-16s" % ("city", "date", "weather", "temp"))
for row in rows:
print("%-16s%-16s%-32s%-16s" % (row[0], row[1], row[2], row[3]))
class WeatherForecast:
def __init__(self):
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre"}
self.cityCode = {"北京": "101010100", "上海": "101020100", "广州": "101280101", "深圳": "101280601"}
def forecastCity(self, city):
if city not in self.cityCode.keys():
print(city + " code cannot be found")
return
url = "http://www.weather.com.cn/weather/" + self.cityCode[city] + ".shtml"
# 爬虫
try:
req = urllib.request.Request(url, headers=self.headers)
data = urllib.request.urlopen(req)
data = data.read()
dammit = UnicodeDammit(data, ["utf-8", "gbk"])
data = dammit.unicode_markup
soup = BeautifulSoup(data, "lxml")
lis = soup.select("ul[class='t clearfix'] li")
for li in lis:
try:
date = li.select('h1')[0].text
weather = li.select('p[class="wea"]')[0].text
temp = li.select('p[class="tem"] span')[0].text + "/" + li.select('p[class="tem"] i')[0].text
print(city, date, weather, temp)
self.db.insert(city, date, weather, temp)
except Exception as err:
print(err)
except Exception as err:
print(err)
def process(self, cities):
self.db = WeatherDB()
self.db.openDB()
for city in cities:
self.forecastCity(city)
print("\n")
print("开始输出数据库:\n")
self.db.show()
self.db.closeDB()
WF = WeatherForecast()
WF.process(["北京", "上海", "广州", "深圳"])
print("\n")
print("输出数据库完成")
2. 运行结果和截图
图2:爬取股票信息后的数据库内容截图
心得体会
在完成作业②的过程中,我学习了如何定向爬取特定网站的股票相关信息,并将数据存储到数据库中。以下是我的一些心得体会:
1,目标网站分析:首先,我选择了东方财富网作为数据源。通过使用浏览器的开发者工具(F12),我分析了股票列表的加载方式,发现股票数据是通过API接口动态获取的。这使得定向爬取股票信息变得更加高效,因为可以直接请求API获取结构化的数据,而无需解析复杂的HTML页面。
2,API请求构建:通过分析API请求的URL和参数,我构建了相应的请求URL。特别注意了分页参数(pn 表示页码,pz 表示每页条数),以便能够爬取多页的数据。
3,数据提取与解析:使用 requests 库发送HTTP请求,并获取返回的JSON数据。通过解析JSON结构,我提取了所需的股票信息字段,包括代码、名称、最新价、涨跌幅、跌涨额、成交量、成交额和涨幅等。
4,数据存储:为了持久化存储爬取到的数据,我选择了SQLite数据库。设计了一个适当的表结构,并使用参数化查询将数据批量插入数据库中。这不仅保证了数据的完整性,也提高了数据存储的效率。
5,使用 pandas 进行数据处理:通过将数据转换为 pandas DataFrame,我能够方便地进行数据展示和初步分析。这也为后续的数据处理和可视化奠定了基础。
6,异常处理与调试:在爬取过程中,可能会遇到网络请求失败、数据缺失或格式不符等问题。通过添加异常处理机制,我能够及时捕捉并处理这些问题,确保程序的稳定运行。同时,打印出错误信息有助于快速定位和修复问题。
7,优化爬取效率:为了提高爬取效率,我采用了循环分页的方式,一次性获取多个页面的数据。此外,通过减少不必要的请求和优化数据提取逻辑,进一步提升了爬取速度。
8,代码规范与模块化:为了提高代码的可读性和维护性,我将数据库操作封装在 StockDB 类中,将爬取逻辑封装在独立的函数中。这种模块化的设计使得代码更加清晰,便于后续的功能扩展和优化。
9,用户交互:通过添加用户输入页面数的功能,我的程序更加灵活,用户可以根据需要选择爬取的页面数量。这提高了程序的通用性和用户体验。
10,学习与提升:此次作业让我深入理解了如何通过API接口获取数据,避免了繁琐的网页解析过程。同时,通过实际操作,我提升了对JSON数据处理、数据库操作和数据分析的能力。
通过完成作业②,我不仅掌握了定向爬取特定网站数据的技术,还学会了如何高效地处理和存储大量结构化数据。这些技能将在我未来的数据采集、分析和项目开发中发挥重要作用。接下来,我计划进一步学习如何处理更加复杂的API接口、如何进行多线程或异步爬取以提升效率,以及如何进行数据的深入分析和可视化展示。
标签:city,self,融合,实践,爬取,采集,weather,print,数据库 From: https://www.cnblogs.com/fufubufff/p/18467505