爬虫 —— 请求网站并提取数据的自动化程序
2.爬虫的基本流程(1) 向服务器发起请求
(2) 获取响应内容
(3) 解析内容
(4) 保存数据
准备爬取的网址:中国气象局-天气预报 (cma.cn)https://weather.cma.cn/
1、如何爬取不同城市的天气预报查看 中国气象局-天气预报 页面的源代码。在源代码中,有:
可以发现:每个城市对应天气预报的URL都有如下形式:
weather.cma.cn/web/weather/XXXXX.html
为分别爬取不同城市的天气预报,可以创建列表,分别保存每个城市的名称以及对应的编码,通过遍历列表list的方式访问每个城市的URL,进而进行对其页面的爬取。
weather.cma.cn/web/weather/ + list[i]
爬取的代码如下:
citynum_list = [58367, 51463, 52889, 54511, 58238, 58606, 58968, 58321, 53463, 50953, 53772, 59287, 56294, 55591, 56778,
58457, 57494, 54342, 54823, 59758, 59493, 53698, 58847, 52866, 57036, 57816, 57083, 57516, 53614, 54161,
57679, 54517, 45005, 45011, 59431]
cityname_list = ['上海', '乌鲁木齐', '兰州', '北京', '南京', '南昌', '台北', '合肥', '呼和浩特', '哈尔滨', '太原', '广州', '成都', '拉萨', '昆明', '杭州',
'武汉', '沈阳', '济南', '海口', '深圳', '石家庄', '福州', '西宁', '西安', '贵阳', '郑州', '重庆', '银川', '长春', '长沙', '天津', '香港',
'澳门', '南宁']
def AskURL(url):
head = {
"User-Agent": "Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 80.0.3987.122 Safari / 537.36"}
request = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
except urllib.error.URLError as e:
if hasattr(e, "code"):
print(e.code)
if hasattr(e, "reason"):
print(e.reason)
return html
# 爬取资源
def GetData(baseurl, citynum_list, cityname_list):
citydate_list = []
# 1.获取页面
for i in range(len(citynum_list) - 1):
url = baseurl + str(citynum_list[i])
html = AskURL(url)
pass
..........................
2、如何从爬取的页面中筛选有用的信息
(1)BeautifulSoup库
查看页面源代码,可以发现,我们需要的信息在块 以及 中,可以采用BeautifulSoup的.find_all方法找到对应的块
soup = BeautifulSoup(html, "html.parser")
# I.当天
for firstdata in soup.find_all('div', class_="pull-left day actived"):
pass
# II.后面的日子
for afterdata in soup.find_all('div', class_="pull-left day"):
pass
firstdata的结果:
afterdata的结果:
这样就获得了一个城市一星期的天气预报,然后就可以使用正则表达式对关心的信息进行筛选了。
(2)Re库正则表达式预处理
find_day = re.compile(r'(.*?)
(.*?)')
find_weather = re.compile(r'(.*?)')
find_temperature = re.compile(r'(.*?)(.*?)')
find_day 的代码:
day = re.findall(find_day, firstdata)[0]
data.append(day[0])
data.append(day[1])
find_weather 的代码:
for i in range(1, 7):
weather = re.findall(find_weather, firstdata)[i]
data.append(weather)
find_temperature 的代码:
temperature = re.findall(find_temperature, firstdata)[0]
data.append(temperature[0])
data.append(temperature[1])
3、保存为Excel文件
(1).xlwt库、xlrd库
保存为excel表的代码:
def SaveExcel(citydate_list, savepath):
book = xlwt.Workbook(encoding="utf-8", style_compression=0)
sheet = book.add_sheet('最近7天天气预报', cell_overwrite_ok=True)
# 标题
col = ("城市", "星期", "日期", "白天天气", "白天风向", "白天风级", "夜间天气", "夜间风向", "夜间风级", "最高气温", "最低气温")
for i in range(0, 11):
sheet.write(0, i, col[i])
# 城市
flag = 1
for i in range(0, len(citydate_list) - 1):
for weekdata in range(0, 7):
sheet.write(flag, 0, citydate_list[i][0])
flag = flag + 1
# 星期
for col in range(0, 10):
flag = 1
for i in range(0, len(citydate_list) - 1):
for weekdata in range(1, 8):
sheet.write(flag, col + 1, citydate_list[i][weekdata][col])
flag = flag + 1
book.save(savepath)
print("文件保存成功!")
print('\n\n\n',citydate_list)
三、源代码
- 源代码:
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
from psycopg2 import connect
import urllib.request
import xlwt
import xlrd
import re
import os
# 正则表达式预编译
find_day = re.compile(r'(.*?)
(.*?)')
find_weather = re.compile(r'(.*?)')
find_temperature = re.compile(r'(.*?)(.*?)')
# 待爬取的城市代码
citynum_list = [58367, 51463, 52889, 54511, 58238, 58606, 58968, 58321, 53463, 50953, 53772, 59287, 56294, 55591, 56778,
58457, 57494, 54342, 54823, 59758, 59493, 53698, 58847, 52866, 57036, 57816, 57083, 57516, 53614, 54161,
57679, 54517, 45005, 45011, 59431]
cityname_list = ['上海', '乌鲁木齐', '兰州', '北京', '南京', '南昌', '台北', '合肥', '呼和浩特', '哈尔滨', '太原', '广州', '成都', '拉萨', '昆明', '杭州',
'武汉', '沈阳', '济南', '海口', '深圳', '石家庄', '福州', '西宁', '西安', '贵阳', '郑州', '重庆', '银川', '长春', '长沙', '天津', '香港',
'澳门', '南宁']
def AskURL(URL):
'''
爬取指定URL的HTML页面
:param URL: 统一资源定位符(UniformResourceLocator)
:return: 爬取的HTML页面
'''
# User - Agent 用户代理
head = {"User-Agent": "Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 80.0.3987.122 Safari / 537.36"}
# Request类来构建一个请求,在请求中需要加入headers(请求头)等信息
request = urllib.request.Request(URL, headers = head)
HTML = ""
try:
response = urllib.request.urlopen(request)
HTML = response.read().decode("utf-8")
except urllib.error.URLError:
print('网页爬取失败!')
return HTML
def GetData(Basis_URL, citynum_list, cityname_list):
'''
爬取页面,对页面进行解析
:param Basis_URL: 待爬取页面的基础URL
:param citynum_list: 每个城市对应的URL后缀列表
:param cityname_list: 每个城市的城市名列表
:return: citydate_list 包含需要的信息
'''
'''
allcity_list[] ---> 保存包含35个城市的城市名,每个城市7天天气
city_list[] ---> 保存每个城市7天天气
data[] ---> 保存一个城市每天的天气预报情况
'''
allcity_list = []
# 1.获取页面
for i in range(len(citynum_list) - 1):
URL = Basis_URL + str(citynum_list[i])
html = AskURL(URL)
city_list = [cityname_list[i]]
# 2.解析页面
soup = BeautifulSoup(html, "html.parser")
# I.当天
for firstdata in soup.find_all('div', class_="pull-left day actived"):
data = []
firstdata = str(firstdata)
# i.日期
day = re.findall(find_day, firstdata)[0]
data.append(day[0])
data.append(day[1])
# ii.天气
for i in range(1, 7):
weather = re.findall(find_weather, firstdata)[i]
data.append(weather)
# iii.温度
temperature = re.findall(find_temperature, firstdata)[0]
data.append(temperature[0])
data.append(temperature[1])
city_list.append(data)
# II.后面的日子
for afterdata in soup.find_all('div', class_="pull-left day"):
data = []
afterdata = str(afterdata)
# i.日期
day = re.findall(find_day, afterdata)[0]
data.append(day[0])
data.append(day[1])
# ii.天气
for i in range(1, 7):
weather = re.findall(find_weather, afterdata)[i]
data.append(weather)
# iii.温度
temperature = re.findall(find_temperature, afterdata)[0]
data.append(temperature[0])
data.append(temperature[1])
city_list.append(data)
# 3.展示爬取结果
for i in range(8):
print(city_list[i])
print('\n')
# 4.加入到总列表中
allcity_list.append(city_list)
return allcity_list
def SaveExcel(allcity_list, Path):
'''
保存为本地Excel文件
:param allcity_list: 保存包含35个城市的城市名,每个城市7天天气
:param Path: 保存路径
:return: Excel文件
'''
book = xlwt.Workbook(encoding="utf-8", style_compression=0)
sheet = book.add_sheet('最近7天天气预报', cell_overwrite_ok=True)
# 标题
col = ("城市", "星期", "日期", "白天天气", "白天风向", "白天风级", "夜间天气", "夜间风向", "夜间风级", "最高气温", "最低气温")
for i in range(0, 11):
sheet.write(0, i, col[i])
# 城市
flag = 1
for i in range(0, len(allcity_list) - 1):
for weekdata in range(0, 7):
sheet.write(flag, 0, allcity_list[i][0])
flag = flag + 1
# 星期
for col in range(0, 10):
flag = 1
for i in range(0, len(allcity_list) - 1):
for weekdata in range(1, 8):
sheet.write(flag, col + 1, allcity_list[i][weekdata][col])
flag = flag + 1
book.save(Path)
print("文件保存成功!")
def SaveDataBase(allcity_list,Path):
'''
保存到数据库系统中
:param allcity_list: 保存包含35个城市的城市名,每个城市7天天气
:param Path: Excel文件保存的路径
:return:
'''
CreateTable(CreateConnect())
InsertTable(CreateConnect(), allcity_list,Path)
# DropTable(CreateConnect())
def CreateConnect():
'''
连接数据库
:return:
'''
try:
# 获取环境变量
# 环境变量是程序和 *** 作系统之间的通信方式
# 有些字符不宜明文写进代码里,比如个人账户密码,如果写进自己本机的环境变量里,程序用的时候通过 os.environ.get() 取出来就行了
env = os.environ
# 如果成功打开数据库时,返回一个连接对象
params = {
'database': env.get('OG_DATABASE', 'postgres'), # 数据库名称
'user': env.get('OG_USER', 'tom'), # 用户名
'password': env.get('OG_PASSWORD', 'Huawei_123'), # 密码
'host': env.get('OG_HOST', '192.168.56.130'), # 主机IP
'port': env.get('OG_PORT', 26000) # 端口号
}
conn: connection = connect(**params)
return conn
except:
print('数据库连接失败!')
def CreateTable(conn):
'''
创建表
:param conn: 连接对象
:return:
'''
# 创建一个光标将用于整个数据库使用Python编程
cursor = conn.cursor()
# 执行SQL语句
cursor.execute('''drop table if exists WeatherForecast''')
cursor.execute('''create table WeatherForecast(
id integer not null primary key,
city_name varchar(500) not null,
weekdate varchar(32),
date varchar(32),
day_weather varchar(50),
day_wind_direct varchar(50),
day_wind_scale varchar(50),
night_weather varchar(50),
night_wind_direct varchar(50),
night_wind_scale varchar(50),
highest_temperature varchar(32),
lowest_temperature varchar(32)
)''')
# 提交当前事务
conn.commit()
# 此方法关闭数据库连接,这并不自动调用commit()。如果只是关闭数据库连接而不调用commit()方法,所有更改将会丢失
conn.close()
print('数据库创建成功!')
def InsertTable(conn, citydate_list,Path):
'''
插入数据
:param conn: 连接对象
:param citydate_list: 保存包含35个城市的城市名,每个城市7天天气
:param Path: Excel文件保存的路径
:return:
'''
cursor = conn.cursor()
# 读取Excel文件
workBook = xlrd.open_workbook(Path)
# 按索引号获取Content内容,sheet索引从0开始
Content = workBook.sheet_by_index(0)
# 写入数据库
for i in range(1, Content.nrows):
row = Content.row_values(i)
cursor.execute(f"insert into WeatherForecast(id,city_name,weekdate,date,day_weather,day_wind_direct,day_wind_scale,night_weather,night_wind_direct,night_wind_scale,highest_temperature,lowest_temperature) values({i},'{row[0]}','{row[1]}','{row[2]}','{row[3]}','{row[4]}','{row[5]}','{row[6]}','{row[7]}','{row[8]}','{row[9]}','{row[10]}')")
conn.commit()
conn.close()
print('数据库插入完毕!')
def DropTable(conn):
'''
删除表
:param conn: 连接对象
:return:
'''
cursor = conn.cursor()
cursor.execute("drop table WeatherForecast")
conn.commit()
conn.close()
print('数据库删除成功!')
if __name__ == "__main__":
Basis_URL = "https://weather.cma.cn/web/weather/"
Path = "各省会城市最近7天天气预报.xls"
# 1.爬取网页
allcity_list = GetData(Basis_URL, citynum_list, cityname_list)
# 2.保存到Excel文件中
SaveExcel(allcity_list, Path)
# 3.保存到数据库中
# SaveDataBase(allcity_list, Path)
print("天气爬取完毕!")
- 运行结果:
- 保存结果:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)