作业①
爬取中国气象网
要求:在中国气象网(http://www.weather.com.cn)给定城市集的7日天气预报,并保存在数据库。
from bs4 import BeautifulSoup
from bs4 import UnicodeDammit
import urllib.request
import sqlite3
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)
self.db.closeDB()
ws = WeatherForecast()
ws.process(["北京", "上海", "广州", "深圳"])
print("completed")
运行结果:
数据被存储在weathers.db数据集中,同时程序打印出爬取结果。

心得体会
- 在构造请求时,可以设置User-Agent头信息,绕过某些反爬虫机制。
- 在解析天气预报页面时,可以使用CSS选择器来定位元素,这种做法更为简洁、易读,并且不容易出错。同时由于某些标签可能缺失,故可以使用使用try...except语句可以避免程序因此崩溃。
- 对于爬取中文网站时乱码问题,我们可以使用UnicodeDammit库来巧妙避免这些问题。
- 可以将爬取的数据存储到SQLite数据库中,这是一个轻量级的关系型数据库,适合小规模的数据存储和管理。
作业②
爬取股票相关信息
要求:用 requests 和 BeautifulSoup 库方法定向爬取股票相关信息,并存储在数据库中。
– 网站:东方财富网:https://www.eastmoney.com/
– 技巧:在谷歌浏览器中进入 F12 调试模式进行抓包,查找股票列表加载使用的 url,并分析 api 返回的值,并根据所要求的参数可适当更改api 的请求参数。根据 URL 可观察请求的参数 f1、f2 可获取不同的数值,根据情况可删减请求的参数。
import requests
import re
import pandas as pd
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.31"}
# 提取数据
def getHtml(page):
url="http://52.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112408730478018317309_1696661490260&pn="+str(page)+"&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&wbp2u=|0|0|0|web&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=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152"
r = requests.get(url,headers=headers)
pat0='"diff":\[\{(.*?)\}\]'
data=re.compile(pat0,re.S).findall(r.text)
return data
#爬取单页股票数据
def getOnePageStock(page):
data=getHtml(page)
datas=data[0].split('},{')
stocks=[]
for i in range(len(datas)):
str1=r'"(\w)+":'
stock=re.sub(str1," ",datas[i]) #将所有的文本都替换成空格
stock =stock.split(",")
stocks.append(stock)
return stocks
page=1
stocks=getOnePageStock(page)
print("已经爬取了第1页")
while page<=5:
page+=1
if getHtml(page)!=getHtml(page-1):
stocks.extend(getOnePageStock(page))
print("已经爬取了第"+str(page)+"页")
else:
break
df=pd.DataFrame(stocks)#将 stocks 变量中的数据转换为 Pandas 数据框(DataFrame)格式
#提取主要数据
df.drop([0,7,8,9,10,12,18,19,20,21,22,23,24,25,26,27,28,29,30],axis=1,inplace=True)
df.index = range(1,len(df) + 1)
df=df[[11,13,1,2,3,4,5,6,14,15,16,17]]
columns = {11:"股票代码",13:"股票名称",1:"最新报价",2:"涨跌幅",3:"涨跌额",4:"成交量",5:"成交额",6:"振幅",14:"最高",15:"最低",16:"今开",17:"昨收"}
df=df.rename(columns=columns)
print(df)
df.to_excel("C:/Users/zwl/Desktop/作业2-2.xlsx")
运行结果:

心得体会
- 在发送HTTP请求时,可以设置User-Agent头信息,绕过某些反爬虫机制。
- 可以使用正则表达式来有效地提取数据。例如,在使用re.compile函数时,可以将匹配模式和标志(re.S)作为参数传递,并使用findall方法来获取所有匹配的结果。
- 在爬取单页股票数据时,可以将每个股票的信息存储在一个列表中,并将列表添加到一个包含所有股票信息的列表中。这样可以方便地处理和组织数据。
作业③
Gif录制F12调试分析过程

爬取中国大学2021主榜
要求:爬取中国大学 2021 主榜(https://www.shanghairanking.cn/rankings/bcur/2021)所有院校信
息,并存储在数据库中,同时将浏览器 F12 调试分析的过程录制 Gif 加入至博客中。
– 技巧:分析该网站的发包情况,分析获取数据的 api
import requests
import openpyxl
import re
if __name__=="__main__":
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.31"}
url='https://www.shanghairanking.cn/_nuxt/static/1695811954/rankings/bcur/2021/payload.js'
response=requests.get(url=url,headers=headers)
response.encoding='utf-8'
page_text=response.text
# print(page_text)
data_regex = r'univData:(.*?),indList'
data = re.findall(data_regex, page_text, re.S)[0]
data = data.lstrip('[').rstrip(']')
names = re.findall("univNameCn:(.*?),univNameEn:", data)
areas = re.findall("province:(.*?),score", data)
univCategory = re.findall("univCategory:(.*?),province", data)
scores = re.findall("score:(.*?),ranking", data)
dict = {'q':'北京','x':'浙江','C':'上海','k':'江苏','s':'陕西','v':'湖北','A':'黑龙江','u':'广东','n':'山东','M':'天津'
,'y':'安徽','t':'四川','D':'福建','B':'吉林','o':'河南','w':'湖南','r':':辽宁','E':'山西','N':'新疆','G':'广西'
,'J':'甘肃','p':'河北','I':'贵州','F':'云南','L':'重庆','K':'内蒙古','aD':'宁夏','z':'江西','Y':'海南','aF':'西藏'
,'aE':'青海'}
sort ={'f':'综合','e':'理工','h':'师范','m':'农业','T':'林业'}
tplt = "{0:^10}\t{1:^10}\t{2:^10}\t{3:{5}^10}\t{4:^10}"
# {5}表示需要填充时使用format的第五个变量进行填充,即使用中文空格
print(tplt.format("排名", "学校名称", "省份", "学校类型", "总分", chr(12288)))
for i in range(30):
print(tplt.format(str(i + 1), names[i].lstrip('"').rstrip('"'),dict[areas[i]].lstrip(':'),sort[univCategory[i]], scores[i], chr(12288)))
wb = openpyxl.Workbook()
ws = wb.active
# 写入数据
ws.cell(1, 1,value="排名")
ws.cell(1, 2, value="学校名称")
ws.cell(1, 3, value="省份")
ws.cell(1, 4, value="学校类型")
ws.cell(1, 5, value="总分")
for i in range(1,30):
ws.cell(row=i+1, column=1, value=i)
ws.cell(row=i+1, column=2, value=names[i].lstrip('"').rstrip('"'))
ws.cell(row=i+1, column=3, value=dict[areas[i]].lstrip(':'))
ws.cell(row=i+1, column=4, value=sort[univCategory[i]])
ws.cell(row=i+1, column=5, value=scores[i])
# 保存文件
wb.save('C:/Users/zwl/Desktop/作业2-3.xlsx')
运行结果:

心得体会
- 在发送请求时,可以设置User-Agent头信息,绕过某些反爬虫机制。
- 在使用正则表达式提取数据时,可以使用非贪婪模式,即在匹配规则后面加上?,以避免匹配过多的内容。
- 在输出结果时,可以使用了chr(12288)来生成中文空格,使得输出对齐更美观。