爬取去哪儿网的旅游景点以及价格和介绍
因为是学习,所以请不要爬取正式环境去测试,因为容易被封,所以我们使用他们的测试环境测试,首先看一下域名:http://piao.qunar.com
我要爬取国内热门城市中的景点,因为爬取的数据我要保存到我的数据库中,所以我们先把数据库环境做好,直接安装mysql数据库,然后创建一个用户名并设置密码,设置密码后需要设置权限,并且设置数据库允许客户端访问,程序才可以写数据到数据库中。
设置允许远程访问并设置权限:
mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'youpassword' WITH GRANT OPTION;##如果不使用root用户可以替换掉自己的用户
重载授权表:
退出mysql数据库:
如果设置只允许程序所在的机器访问把“%”换成自己的IP即可。这里设置的权限比价大,只是测试使用。
创建数据库表
首先创建的是数据库,因为介绍中有汉字所以需要utf-8
CREATE DATABASE `quna` CHARACTER SET utf8 COLLATE utf8_general_ci;
创建库后在创建表
CREATE TABLE qu_na(
id INT(20) AUTO_INCREMENT PRIMARY KEY COMMENT 'id',
city_name VARCHAR(20) NOT NULL COMMENT '城市名',
jd_name VARCHAR(30) NOT NULL COMMENT '景点名称',
jd_jb VARCHAR(20) NOT NULL COMMENT '景点级别',
jd_jieshao VARCHAR(50) NOT NULL COMMENT '景点介绍',
jd_price VARCHAR(10) NOT NULL COMMENT '景点价格',
jd_xiaoliang VARCHAR(10) NOT NULL COMMENT '景点销量');
已经了解到自己要爬取到内容,下面就根据自己爬取到内容进行分析:
首先,访问页面找到一些热点城市的代码,我们做一些标记:
就是全国热门城市,找到城市列表,分别取每个热门城市的[href]链接,然后对页面在具体分析:
如上图,所有的热门城市都在class="mp-sidebar-list"中,我们需要爬取的过程中爬取ul中的li,因为li中包含了所有城市。
#!/usr/bin/env python
#-*-coding:utf-8-*-
import requests
from bs4 importBeautifulSoup
import re
# 解析出每个城市及其该城市对应的url
def parse_city(url):
#这里先定义一下url的状态,如果错误就不执行
status = requests.get(url).status_code
if status ==200:
html = requests.get(url, headers=headers)
html = html.text
soup =BeautifulSoup(html,'lxml')#
city = soup.find_all('ul',{'class':'mp-sidebar-list','mp-role':'hotCityList'})[0].find_all('li')
for i in city:
# 得到每个城市的名字和对应的url
city_name = i.a.text
city_url = i.a['href']
city_url = url + city_url
print("热门城市:",city_name,"热门城市路径:",city_url)
else:
return404
if __name__ =='__main__':
headers ={
'User-Agent':'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)',}
start_url ='http://piao.qunar.com/'
parse_city(start_url)
查看一下执行结果:
热门城市:北京热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=北京®ion=北京&from=mpshouye_hotcity
热门城市:上海热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=上海®ion=上海&from=mpshouye_hotcity
热门城市:成都热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=成都®ion=成都&from=mpshouye_hotcity
热门城市:三亚热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=三亚®ion=三亚&from=mpshouye_hotcity
热门城市:广州热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=广州®ion=广州&from=mpshouye_hotcity
热门城市:重庆热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=重庆®ion=重庆&from=mpshouye_hotcity
热门城市:深圳热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=深圳®ion=深圳&from=mpshouye_hotcity
热门城市:西安热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=西安®ion=西安&from=mpshouye_hotcity
热门城市:杭州热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=杭州®ion=杭州&from=mpshouye_hotcity
热门城市:厦门热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=厦门®ion=厦门&from=mpshouye_hotcity
热门城市:武汉热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=武汉®ion=武汉&from=mpshouye_hotcity
热门城市:大连热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=大连®ion=大连&from=mpshouye_hotcity
热门城市:苏州热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=苏州®ion=苏州&from=mpshouye_hotcity
热门城市:青岛热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=青岛®ion=青岛&from=mpshouye_hotcity
热门城市:天津热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=天津®ion=天津&from=mpshouye_hotcity
热门城市:南京热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=南京®ion=南京&from=mpshouye_hotcity
热门城市:香港热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=香港®ion=香港&from=mpshouye_hotcity
热门城市:桂林热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=桂林®ion=桂林&from=mpshouye_hotcity
热门城市:郑州热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=郑州®ion=郑州&from=mpshouye_hotcity
热门城市:昆明热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=昆明®ion=昆明&from=mpshouye_hotcity
所有的热门城市已经爬取完成,下面对于每一个城市爬取城市,景点,景点级别,景点介绍,景点价格,景点销售。分别提取出来,然后在写到数据库中。
已经找到所有的热门城市,下面针对所有的热门城市做一下分析如图:
先找出所有的热门城市,在把每个热门城市的景点都找出来,然后对于每个景点在分析,需要上面的函数调用下面的函数,在上面函数打印热门城市下调用一下这个函数:
def city_page(city_name, city_url):
html = requests.get(city_url, headers=headers)
html = html.text
soup =BeautifulSoup(html,'lxml')
page = soup.find_all('div',{'class':'pager'})[0].find_all('a')
# 得到a标签中的href
page_url = page[0]['href']
# 得到下一页的url,这个url由我们来指定,只需把页数前面的字符串匹配出来即可
page_select_url = re.findall('(.*page=)', page_url)[0]
# 将完整的页数的url拼接起来
page_select_url ='http://piao.qunar.com'+ page_select_url
# 这里选-2是有深意的,因为在选择每一页的地方倒一是下一页,而倒二则是尾页数
page_num =int(page[-2].text)
print('有%s页的数据'% page_num)
for i in range(1, page_num +1):
# 遍历得到某个城市中所有页数
print('第%d页信息'% i)
parse_page_url = page_select_url + str(i)
print('网页地址:', parse_page_url)
之后后的结果:
热门城市:北京热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=北京®ion=北京&from=mpshouye_hotcity
有257页的数据
第1页信息
网页地址: http://piao.qunar.com/ticket/list_%E5%8C%97%E4%BA%AC_%E5%8C%97%E4%BA%AC.html?from=mpshouye_hotcity&page=1
第2页信息
网页地址: http://piao.qunar.com/ticket/list_%E5%8C%97%E4%BA%AC_%E5%8C%97%E4%BA%AC.html?from=mpshouye_hotcity&page=2
第3页信息
网页地址: http://piao.qunar.com/ticket/list_%E5%8C%97%E4%BA%AC_%E5%8C%97%E4%BA%AC.html?from=mpshouye_hotcity&page=3
第4页信息
网页地址: http://piao.qunar.com/ticket/list_%E5%8C%97%E4%BA%AC_%E5%8C%97%E4%BA%AC.html?from=mpshouye_hotcity&page=4
第5页信息
网页地址: http://piao.qunar.com/ticket/list_%E5%8C%97%E4%BA%AC_%E5%8C%97%E4%BA%AC.html?from=mpshouye_hotcity&page=5
第6页信息
网页地址: http://piao.qunar.com/ticket/list_%E5%8C%97%E4%BA%AC_%E5%8C%97%E4%BA%AC.html?from=mpshouye_hotcity&page=6
第7页信息
网页地址: http://piao.qunar.com/ticket/list_%E5%8C%97%E4%BA%AC_%E5%8C%97%E4%BA%AC.html?from=mpshouye_hotcity&page=7
第8页信息
针对每一个热门城市中的景点进行分析代码如下图:
我们需要找到的城市名称,景点名称,景点级别,景点介绍,景点价格,景点销量。需要对于每个热门城市的页面进行分析:
#解析每个城市每一页的信息
def parse_page(city_name, parse_page_url):
html = requests.get(parse_page_url, headers=headers)
html = html.text
soup =BeautifulSoup(html,'lxml')
jingdian = soup.find_all('div',{'class':'result_list','id':'search-list'})[0].find_all('div',
{'class':'sight_item'})
for c in jingdian:
# 景点名
jd_name = c.find_all('a',{'data-click-type':'l_title','class':'name'})[0].text
# 景点级别,有的景区无级别,所以要设置一个异常
try:
jd_jb = c.find_all('span',{'class':'level'})[0].text
except:
jd_jb ='普通景区'
# text得到的是 地址:北京市东城区景山前街4号 这种格式,所以以空格拆分,取后面那个
jd_address = c.find_all('p',{'class':{'address','color999'}})[0].text.split()[-1]
# 景点介绍
jd_jieshao = c.find_all('div',{'class':{'intro','color999'}})[0].text
# 景点价格,有的是免费,并无价格这一参数,所以设置一个异常
try:
jd_price = c.find_all('span',{'class':'sight_item_price'})[0].find_all('em')[0].text
except:
jd_price =0
# 有的是免费,并销量这一参数,所以设置一个异常
try:
jd_xiaoliang = c.find_all('span',{'class':'hot_num'})[0].text
# 景点销量
jd_xiaoliang =int(jd_xiaoliang)
except:
jd_xiaoliang =0
print('{0} {1} {2} {3} {4}'.format(jd_name, jd_jb, jd_jieshao, jd_price, jd_xiaoliang))
打印结果:
热门城市:北京热门城市路径: http://piao.qunar.com//ticket/list.htm?keyword=北京®ion=北京&from=mpshouye_hotcity
故宫5A景区一起来逛逛紫禁城”庙会“吧2012810
八达岭长城5A景区不到长城非好汉1402799
颐和园5A景区保存完整的一座皇家行宫御苑361206
天安门广场普通景区我爱北京天安门,天安门上太阳升203573
圆明园4A景区追忆昔日万园之园254052
鸟巢5A景区北京的地标,中华民族崛起的象征49832
水立方普通景区中国的荣耀,阳光下的晶莹水滴14526
什刹海4A景区老北京的温柔乡,北京签到地51692
天坛公园5A景区探寻古代皇帝祭天仪式的奥秘2.3222
慕田峪长城5A景区电影《非诚勿扰》取景地20598
至此,爬取已经完成,下面就是把爬取的页面写到数据中,下面那完整代码贴出来。
#!/usr/bin/env python
#-*-coding:utf-8-*-
import requests
from bs4 importBeautifulSoup
import re
import pymysql
# 解析出每个城市及其该城市对应的url
def parse_city(url):
status = requests.get(url).status_code
if status ==200:
html = requests.get(url, headers=headers)
html = html.text
soup =BeautifulSoup(html,'lxml')
city = soup.find_all('ul',{'class':'mp-sidebar-list','mp-role':'hotCityList'})[0].find_all('li')
for i in city:
# 得到每个城市的名字和对应的url
city_name = i.a.text
city_url = i.a['href']
city_url = url + city_url
print("热门城市:",city_name,"热门城市路径:",city_url)
city_page(city_name, city_url)
else:
return404
# 解析出每个城市的url的下一页
def city_page(city_name, city_url):
html = requests.get(city_url, headers=headers)
html = html.text
soup =BeautifulSoup(html,'lxml')
page = soup.find_all('div',{'class':'pager'})[0].find_all('a')
# 得到a标签中的href
page_url = page[0]['href']
# 得到下一页的url,这个url由我们来指定,只需把页数前面的字符串匹配出来即可
page_select_url = re.findall('(.*page=)', page_url)[0]
# 将完整的页数的url拼接起来
page_select_url ='http://piao.qunar.com'+ page_select_url
# 这里选-2是有深意的,因为在选择每一页的地方倒一是下一页,而倒二则是尾页数
page_num =int(page[-2].text)
#print('有%s页的数据' % page_num)
for i in range(1, page_num +1):
# 遍历得到某个城市中所有页数
#print('第%d页信息' % i)
parse_page_url = page_select_url + str(i)
#print('网页地址:', parse_page_url)
# 将每一页的url都传递到parse_page中进行解析
parse_page(city_name, parse_page_url)
# 解析每个城市每一页的信息
def parse_page(city_name, parse_page_url):
html = requests.get(parse_page_url, headers=headers)
html = html.text
soup =BeautifulSoup(html,'lxml')
jingdian = soup.find_all('div',{'class':'result_list','id':'search-list'})[0].find_all('div',
{'class':'sight_item'})
for c in jingdian:
# 景点名
jd_name = c.find_all('a',{'data-click-type':'l_title','class':'name'})[0].text
# 景点级别,有的景区无级别,所以要设置一个异常
try:
jd_jb = c.find_all('span',{'class':'level'})[0].text
except:
jd_jb ='普通景区'
# text得到的是 地址:北京市东城区景山前街4号 这种格式,所以以空格拆分,取后面那个
jd_address = c.find_all('p',{'class':{'address','color999'}})[0].text.split()[-1]
# 景点介绍
jd_jieshao = c.find_all('div',{'class':{'intro','color999'}})[0].text
# 景点价格,有的是免费,并无价格这一参数,所以设置一个异常
try:
jd_price = c.find_all('span',{'class':'sight_item_price'})[0].find_all('em')[0].text
except:
jd_price =0
# 有的是免费,并销量这一参数,所以设置一个异常
try:
jd_xiaoliang = c.find_all('span',{'class':'hot_num'})[0].text
# 景点销量
jd_xiaoliang =int(jd_xiaoliang)
except:
jd_xiaoliang =0
#print('{0} {1} {2} {3} {4}'.format(jd_name, jd_jb, jd_jieshao, jd_price, jd_xiaoliang))
mysql(city_name, jd_name, jd_jb, jd_jieshao, jd_price, jd_xiaoliang)
# 定义一个类,将连接MySQL的操作写入其中
class down_mysql:
def __init__(self, city_name, jd_name, jd_jb, jd_jieshao, jd_price, jd_xiaoliang):
self.city_name = city_name
self.jd_name = jd_name
self.jd_jb = jd_jb
self.jd_jieshao = jd_jieshao
self.jd_price = jd_price
self.jd_xiaoliang = jd_xiaoliang
self.connect = pymysql.connect(
host='10.211.55.14',
db='quna',
port=3306,
user='root',
passwd='123456',
charset='utf8',
use_unicode=False
)
self.cursor =self.connect.cursor()
# 保存数据到MySQL中
def save_mysql(self):
sql ="insert into qu_na(city_name,jd_name,jd_jb,jd_jieshao,jd_price,jd_xiaoliang) VALUES (%s,%s,%s,%s,%s,%s)"
try:
self.cursor.execute(sql,(
self.city_name,self.jd_name,self.jd_jb,self.jd_jieshao,self.jd_price,self.jd_xiaoliang))
self.connect.commit()
print('数据插入成功')
except:
print('数据插入错误')
def mysql(ciry_name, jd_name, jd_jb, jd_jieshao, jd_price, jd_xiaoliang):
# 新建类,将数据保存在MySQL中
down = down_mysql(ciry_name, jd_name, jd_jb, jd_jieshao, jd_price, jd_xiaoliang)
down.save_mysql()
if __name__ =='__main__':
headers ={
'User-Agent':'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)',}
start_url ='http://piao.qunar.com/'
parse_city(start_url)
这里需要注意的是,这里爬取的是http,https需要使用ssl模块,并且增加一句
ssl._create_default_https_context = ssl._create_unverified_context
放在定义的url前面。
如果你是新同学,长按下面二维码 - 识别图中二维码 - 关注,就可以每天一起学Python了。
|