作业①
实验内容
要求
在中国气象网(http://www.weather.com.cn)给定城市集的7日天气预报,并保存在数据库。
输出信息
代码
# Connect to database
conn = sqlite3.connect('weather.db')
cursor = conn.cursor()
# Check if table exists
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='WEATHER'")
table_exists = cursor.fetchone()
# Create table if it doesn't exist
if not table_exists:
conn.execute('''CREATE TABLE WEATHER
(ID INTEGER PRIMARY KEY AUTOINCREMENT,
PLACE TEXT NOT NULL,
DATE TEXT NOT NULL,
WEATHER_INFO TEXT NOT NULL,
TEMPERATURE TEXT NOT NULL);''')
conn.close()
def insert_weather_data(place, date, weather_info, temperature):
# Connect to database
conn = sqlite3.connect('weather.db')
# Insert data into table
conn.execute(f"INSERT INTO WEATHER (PLACE, DATE, WEATHER_INFO, TEMPERATURE) VALUES ('{place}', '{date}', '{weather_info}', '{temperature}')")
# Commit changes and close connection
conn.commit()
conn.close()
url="http://www.weather.com.cn/weather/101010100.shtml"
try:
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)
data=data.read()
dammit=UnicodeDammit(data,["utf-8","gbk"])
data=dammit.unicode_markup
soup=BeautifulSoup(data,"html.parser")
lis=soup.select("ul[class='t clearfix'] li")
place = soup.select("div[class='crumbs fl'] a")[1].text
index = 1
print(f"序号\t地区\t日期\t天气信息\t温度")
for li in lis:
try:
date=li.select('h1')[0].text
weather=li.select('p[class="wea"]')[0].text
if li.select('p[class="tem"] span') == []:
temp=li.select('p[class="tem"] i')[0].text
else:
temp=li.select('p[class="tem"] span')[0].text+" / "+li.select('p[class="tem"] i')[0].text
print(f"{index}\t{place}\t{date}\t{weather}\t{temp}")
insert_weather_data(place, date, weather, temp)
index += 1
except Exception as err:
print(err)
except Exception as err:
print(err)
结果

实验心得
这个实验让我更加熟悉了Python网络爬虫的常用库的使用。同时,我还学到了如何连接和操作数据库,将获取到的数据存储在数据库中,以便后续的数据处理和分析。通过爬取网页上的天气数据,并将其保存在数据库中,我们可以方便地获取和管理大量的天气信息,为后续的数据分析和应用提供基础数据。
作业②
实验内容
要求
用requests和BeautifulSoup库方法定向爬取股票相关信息,并存储在数据库中。
候选网站:东方财富网:https://www.eastmoney.com/
新浪股票:http://finance.sina.com.cn/stock/
技巧:在谷歌浏览器中进入F12调试模式进行抓包,查找股票列表加载使用的url,并分析api返回的值,并根据所要求的参数可适当更改api的请求参数。根据URL可观察请求的参数f1、f2可获取不同的数值,根据情况可删减请求的参数。
参考链接:https://zhuanlan.zhihu.com/p/50099084
输出信息
代码(省略数据库连接函数)
api = "https://93.push2.eastmoney.com/api/qt/clist/get"
parms = {
"pn": "1",
"pz": "20",
"po": "1",
"np": "1",
"fltt": "2",
"invt": "2",
"fid": "f3",
"fs": "m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"fields": "f12,f14,f2,f3,f4,f5,f6,f7,f15,f16,f17,f18",
"_": "1696658826129"
}
key = {
"f12": "代码",
"f14": "名称",
"f2": "最新价",
"f3": "涨跌幅",
"f4": "涨跌额",
"f5": "成交量",
"f6": "成交额",
"f7": "振幅",
"f15": "最高价",
"f16": "最低价",
"f17": "今开",
"f18": "昨收",
}
limit = 100
count = 0
r = requests.get(api, params=parms)
json_data = r.json()["data"]
total = json_data["total"]
print("序号", end="\t")
for i in key.keys():
print(key[i], end="\t")
print()
while count < limit and count < total:
for i in json_data["diff"]:
print(str(count + 1), end="\t")
for j in key.keys():
print(i[j], end="\t")
insert_weather_data(i["f12"], i["f14"], i["f2"], i["f3"], i["f4"],
i["f5"], i["f6"], i["f7"], i["f15"], i["f16"],
i["f17"], i["f18"])
print()
count += 1
if count >= limit:
break
parms["pn"] = str(int(parms["pn"]) + 1)
r = requests.get(api, params=parms)
json_data = r.json()["data"]
结果

实验心得
这个实验让我更加熟悉使用开发者工具提取所需数据api的方法。我学到了如何根据不同的需求和情况调整API的请求参数,以获取所需的数据。同时,我也意识到了合理分析网页结构和抓包的重要性,这有助于我们理解网站的数据获取方式,并更好地进行定向爬取。这个实验不仅提升了我的网络爬虫技能,还为我进一步学习和应用数据分析提供了基础。
作业③
实验内容
要求
爬取中国大学2021主榜(https://www.shanghairanking.cn/rankings/bcur/2021)所有院校信息,并存储在数据库中,同时将浏览器F12调试分析的过程录制Gif加入至博客中。
技巧:分析该网站的发包情况,分析获取数据的api
输出信息

代码(省略数据库连接函数与字典信息)
url = 'https://www.shanghairanking.cn/_nuxt/static/1695811954/rankings/bcur/202311/payload.js'
r = requests.get(url, timeout=20)
if r.status_code == 200:
r.encoding = 'utf-8'
# 变量字典映射
a = ()
b = ''
c = b.split(', ')
dic_tmp = dict(zip(c,a))
# 解析数据
datas = re.findall('\{(univUp.*?\})\}',r.text,re.S)
re_compair = r'univNameCn:"(.*)",univNameEn:(.*?),.*univTags:(.*],?),.*univCategory:(.*),province:(.*),score:(.*),ranking:(.*?),.*indData:{"411":(.*),"412":(.*),"413":(.*),"414":(.*),"415":(.*),"416":(.*),"417":(.*),"418":(.*),"419":(.*),"420":(.*)}'
dds = []
# 解析数据
for one_data in datas:
dd = re.findall(re_compair,one_data,re.S)
data_tmp = []
for key in dd[0]:
if key in c:
key = dic_tmp[key]
elif ']' in key:
key_str = []
key = key.replace('[','').replace(']','').split(',')
if 'i' in key or 'l' in key or 'j' in key:
for kk in key:
key_str.append(dic_tmp[kk])
key = ','.join(key_str)
data_tmp.append(key)
dds.append(data_tmp)
print("排名", "学校", "省市", "类型", "总分", end="\t")
print()
for i in dds:
insert_weather_data(i[6],i[0],i[4],i[3],i[5])
print(i[6],i[0],i[4],i[3],i[5],end='\t')
print()
结果

实验心得
实验3是耗时最长的一个实验,在抓取api数据时发现部分数据被混淆。结果分析在返沪的js头尾包含解码所需内容。
__NUXT_JSONP__("/rankings/bcur/202311", (function(...)))
...
("", false, null, 0, "理工", "综合",....)
两端内容为KV对,可以在组合后进行对混淆内容进行解码(混淆内容如下,b、a、e等字母可在字典中找到对应值)
{
univUp: "xinjiang-institute-of-engineering",
univLogo: "logo-jpg\u002F9851006000.jpg",
univNameCn: "新疆工程学院",
univNameEn: "Xinjiang Institute of Engineering",
inbound: b,
liked: b,
univLikeCount: d,
univTags: [],
univNameRemark: a,
univCategory: e,
province: N,
score: 85.2,
ranking: oP,
rankChange: c,
rankOverall: oP,
indData: {
"411": a,
"412": a,
"413": a,
"414": a,
"415": a,
"416": a,
"417": a,
"418": a,
"419": a,
"420": a
}
}
这个实验让我更加熟悉了通过API来获取数据的方法,同时我也意识到了解码内容的重要性。