目的:
推荐小众城市旅游及爬取某一城市的景点信息和游记信息。
第一部分
首先从目的地页面获得各省专属5位数字编号,之后进入各省城市列表获得热门城市专属5位数字编号。
1.获得直辖市编号和热门省编号,http://www.mafengwo.cn/mdd/
def get_province_url(url):
htmlaa = get_html_text(url)
soup = BeautifulSoup(htmlaa, 'lxml')
municipality_directly_info(soup) # 处理直辖市信息
dts = soup.find('div', class_='hot-list clearfix').find_all('dt')
name = []
provice_id = []
urls = []
print('正在处理所有非直辖市信息(解析出来的数据保存在数据库中)')
for dt in dts:
all_a = dt.find_all('a')
#print(all_a)
for a in all_a:
name.append(a.text)
#print(name)
link = a.attrs['href']
provice_id.append(re.search(r'/(\d.*).html', link).group(1)) # 得到这个省的编码
#print(provice_id)
datacitylist= link.replace('travel-scenic-spot/mafengwo', 'mdd/citylist')
urls.append(parse.urljoin(url, datacitylist))
return name, provice_id, urls
2.获得热门省中的全部热门城市。通过对比直辖市和热门省可以发现,除了直辖市之外的热门地区都会有热门城市。
在爬取每个省份的热门城市时,不是静态网页,要通过post请求,找到最大的页码,遍历页码,依次爬取每一页的城市信息(得到每个城市的名字, 链接, 去过人数)。
def get_post(page, provice_id):
data = {'mddid': provice_id, 'page': page}
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"}
response = requests.post('http://www.mafengwo.cn/mdd/base/list/pagedata_citylist', data=data,headers=headers)
#print(response.text)
info, nums = get_city_info(response)#得到每个城市的名字, 链接, 去过人数
return (info, nums)
def parse_city(html, provice_id):
provice_info = {}
soup = BeautifulSoup(html, 'lxml')
pages = int(soup.find(class_="pg-last _j_pageitem").attrs['data-page'])#得到此省热门城市总页数
city_info = []
sum_nums = 0
tPool = ThreadPoolExecutor(20)
ac = []
for page in range(1, pages + 1):
t = tPool.submit(get_post, page, provice_id)
ac.append(t)
tPool.shutdown()
for i in ac:
info, nums = i.result()
sum_nums += nums
city_info.extend(info)
provice_info['sum_num'] = sum_nums#sum_nums这个省份的流量
provice_info['citys'] = city_info#city_id5位编码,city_name城市名字,人次nums
#print("parse_city中的provice_info值:", provice_info)
return provice_info
def get_city_oenbyone(url, name, provice_id):
#print('正在解析',url)
html = get_html_text(url)
provice_info = parse_city(html, provice_id)
provice_info['provice_id'] = provice_id
provice_info['provice_name'] = name
#print("存储{}省的信息".format(name))
save_city_info(provice_info)
#print("get_city_oenbyone的provice_info:",provice_info)
def get_city_id():
url = "http://www.mafengwo.cn/mdd/"
name, provice_id, urls = get_province_url(url)
#print(name, provice_id, urls)
Ppool = ProcessPoolExecutor(5)
for url1, name1, provice_id1 in zip(urls, name, provice_id):
#print(url1)
Ppool.submit(get_city_oenbyone, url1, name1, provice_id1)
Ppool.shutdown()
3.数据库存储城市信息,将爬取到的所有目的地的名字、5位id、省份名称、省份5位id、去过的人数都存储到数据库中。
def save_city_info(provice_info):
#print(provice_info)
provice_id=provice_info['provice_id']
provice_name=provice_info['provice_name']
sum_num = provice_info['sum_num']
sql_pro = "insert into hot_provice(provice_id,provice_name,sum_num) VALUES (%s,%s,%s)"
value_pro = (provice_id, provice_name, sum_num)
# print(value)
mycursor.execute(sql_pro, value_pro)
mydb.commit()
#print(provice_id,priovice_name)
for key,values in provice_info.items():
#print(key,values)
if type(values)==list:
for va in values:
#print(va)
city_id = va.get("city_id")
city_name=va.get("city_name")
nums=va.get("nums")
sql = "insert into citys(provice_id,provice_name,city_id,city_name,nums) VALUES (%s,%s,%s,%s,%s)"
value=(provice_id,provice_name,city_id,city_name,nums)
#print(value)
mycursor.execute(sql,value)
mydb.commit()
#print("succese")
爬取结果展示:存储了大约2000多条城市数据,截取了部分城市信息展示:
第二部分
数据分析
通过读取excel表中的城市专属5位id和城市姓名,爬取所有城市标签、景点、食物数据,比较分析生成图。
DataFrame是Python中Pandas库中的一种数据结构,它类似excel,是一种二维表。将爬取的数据存放在DataFrame。
用pyecharts作图,pyecharts 是一个用于生成 Echarts 图表的类库。 Echarts 是百度开源的一个数据可视化 JS 库。主要用于数据可视化。
爬取这三个页面:
a.标签页面
b.美食页面
c.景点页面
将爬取所有城市的标签总数量、景点信息、食物信息的过程封装成函数,并保存到excel文件中。
# 获得城市信息
def get_city_info(city_name,city_id):
city_base_info = get_city_base(city_name, city_id)
city_jd_info = get_ci