前言

这篇内容讲解js生成内容型,上一篇讲解的所需内容是全部在html源码中可以找得到的,而比如携程网随便打开一个旅店的页面,像图1酒店点评下面的位置等信息在开发者工具中的html代码中可看到在类为bar_score的div中,可是查看源代码搜索bar_score却并没有搜索结果,原因是因为这部分内容是由js代码生成,然后在页面渲染时填充进div中,故源代码中是找不到的。

图1

解决方式:Seleunium+BeautifulSoup

1.Selenium介绍####

Selenium本来是作为一个自动化测试工具。它可以模拟浏览器行为,比如打开浏览器,点击某个元素等等。所以可以利用它获取页面加载后的元素

安装

大多数的python第三方库都可以在以下网站中搜索找到,[python packageIndex]。后面提到的第三方库均可在该网站中下载。(https://pypi.python.org/)

Selenuim仅支持部分浏览器,这里以火狐浏览器为例,并且需要最好下载配套的Selenium和fiirefox,否则可能会遇到版本不兼容问题。这里所用到的是selenium2.42.1和firefox27.0.1(好老)。

操作

打开一个浏览器和网址

from selenium import webdriver

driver = webdriver.Firefox() #打开火狐浏览器

url = 'https://www.baidu.com'

driver.set_page_load_timeout(20) #设置页面超时时间

driver.get(url) #打开对应网址

常用方式定位元素

等待

Selenium中的等待,有时候页面加载需要一定时间,如果立即定位元素可能会出现获取不到元素的错误,所以需要设置等待。

1.强制等待sleep(xx),强制让闪电侠等xx时间,不管浏览器能不能跟上速度,还是已经提前到了,都必须等xx秒。

sleep(3)

2.隐形等待是设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步。隐性等待,最长等30秒

driver.implicitly_wait(30)

3.显性等待,WebDriverWait,配合该类的until()和until_not()方法,就能够根据判断条件而进行灵活地等待了。它主要的意思就是:程序每隔xx秒看眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException。隐性等待和显性等待可以同时用,但要注意:等待的最长时间取两者之中的大者

from selenium.webdriver.support.wait import WebDriverWait

WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator))

2.BeautifulSoup####

Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库,Beautiful Soup 3 目前已经停止开发,推荐在现在的项目中使用Beautiful Soup 4,不过它已经被移植到BS4了,也就是说导入时我们需要 import bs4 。

from bs4 import BeautifulSoup

from bs4 import BeautifulSoup

soup = BeautifulSoup(html_doc,"html.parser")

comment_soup = index.findAll("div", { "class" : "v2_reviewsitem" })

3.xlwt、xlrd、xlutils进行excel读写操作

xlwt::对excel进行写操作

基本操作如下,详情可参考以下文档:http://xlwt.readthedocs.io/en/latest/genindex.html

file = xlwt.Workbook() #新建一个工作簿

sheet1 = file.add_sheet(u'sheet1',cell_overwrite_ok=True) #新建一个工作表,并设置可被改写

sheet1.col(0).width=256*22 #设置第一列的列宽,xlwt的列宽是以256为一个单位

style = xlwt.easyxf('align: wrap on, vert centre, horiz center') #easyxf设置表格样式,此处设置align为垂直水平居中

sheet1.write(0,1,‘text',style) #向第1行第2列以style样式写入text字符串

xlrd:对excel进行读操作

rb_file = xlrd.open_workbook('D:/score.xls') #打开文件

# 获取指定sheet的方式

sheet1 = rb_file.get_sheet(0)

sheet2 = rb_file.sheet_by_index(1) # sheet索引从0开始

sheet3 = rb_file.sheet_by_name('sheet2')

# sheet的姓名、行列操作

print sheet2.name,sheet2.nrows,sheet2.ncols

rows = sheet2.row_values(3) # 获取第四行内容

cols = sheet2.col_values(2) # 获取第三列内容

#单元格操作

print sheet2.cell(1,0).value.encode('utf-8')

print sheet2.cell_value(1,0).encode('utf-8')

print sheet2.row(1)[0].value.encode('utf-8')

print sheet2.cell(1,0).ctype

xlutils:对excel进行追加修改操作

追加方法如下,通过对原有文件建立一个临时副本,在副本后末尾写入新数据,再将原有文件覆盖

rb_file = xlrd.open_workbook('D:/score.xls')

nrows = rb_file.sheets()[0].nrows #获取已存在的excel表格行数

wb_file = copy(rb_file) #复制该excel

sheet1 = wb_file.get_sheet(0) #建立该excel的第一个sheet副本,通过sheet_by_index()获取的sheet没有write()方法

try:

for i in range(0,len(score_list)):

for j in range(0,len(score_list[i])):

#将数据追加至已有行后

sheet1.write(i+nrows,j,score_list[i][j])

except Exception, e:

print e

wb_file.save('D:/score.xls')

携程爬虫实现##

首先进入酒店列表的页面,此处是在首页设置城市为武汉之后进来的页面,在酒店列表获取红圈中的如下信息,查看详情是获取该按钮对应的链接地址,方便后面进入酒店的详情页面

图一

然后是酒店详情页面的如下信息

图二

最终获取数据结果如下图

程序的整体思路是,

1.以每一页为一个单位,爬取一页数据并存储完毕后,使用selenium模拟点击下一页。

2.每一页使用selenuim获取酒店列表的单条酒店信息的整体html,转换成beautifulsoup所需格式存储至hotel_list。

3.遍历hotel_list,使用beautifulsoup提取图一的信息,再跳转至详情页面爬取图二中的信息。将图一图二信息整合至hotel_info的元组,最后追加至info_list列表,构成一页所有酒店的所需信息。

4.每爬取一页存储至excel。因为使用selenium不断打开浏览器操作多了之后会出现浏览器无响应的情况,为避免最后没有数据,所有采用爬取一页存一页的方式。

代码简单讲解:

需下载的库,bs4,xlwt,xlrd,xlutils,selenium

程序结构main 为程序入口,bulid_excel建立excel文件供存储数据,read_hotel爬取数据,并设置每一页爬取完毕后调用save_score向建立的excel追加写入数据。

# -*- coding: utf-8 -*- #这行很重要,所有python代码最好都以utf-8形式编码,以防止中文乱码

import urllib2 #和urlib类似,但是可以构造request请求

from bs4 import BeautifulSoup

import re

import os #文件操作库

import xlwt

import xlrd

from xlutils.copy import copy

from selenium import webdriver

from selenium.common.exceptions import TimeoutException

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

import time #时间操作库,强制等待sleep需引入

import traceback #一个很好的错误追踪

import socket

#driver.set_page_load_timeout(30)

socket.setdefaulttimeout(30)

class CommentContent:

#读取武汉酒店列表

def read_hotel(self):

driver = webdriver.Firefox() #打开浏览器

driver.maximize_window() #最大化窗口

page = 0 #提示作用

index_url = 'http://hotels.ctrip.com/hotel/wuhan477#ctm_ref=ctr_hp_sb_lst'

driver.get(index_url) #打开待爬取酒店列表页面

#模拟浏览器勾选酒店类型为青年旅社

btn_qn = driver.find_element_by_id('feature-35')

btn_qn.click()

time.sleep(5)

info_list = []

hotel_list = [] #存储所有带爬取酒店的信息

#range()中的数字可指定需要爬取的页数

for i in range(4):

hotel_loc = []

#获取该页的酒店列表

hotel_loc = driver.find_elements_by_xpath("//div[@class='searchresult_list searchresult_list2']")

count = 0

page_count = len(hotel_loc)

print page_count

while count < page_count:

try:

hotel = ''

#获取酒店列表的html,供beautiful转换后方便提取

hotel = hotel_loc[count].get_attribute("innerHTML")

hotel_list.append(BeautifulSoup(hotel,"html.parser"))

count += 1

except Exception,e:

#print e

print 'get hotel html error'

#continue

#点击下一页按钮

btn_next = driver.find_element_by_id('downHerf')

btn_next.click()

time.sleep(10)

count = 0

hotel_count = len(hotel_list)

#遍历酒店列表里的每一条酒店信息

while count < hotel_count:

try:

#获取每一条酒店的总体评分、用户推荐%数、查看详情的链接地址

hotel_name = hotel_list[count].findAll("h2",{"class","searchresult_name"})[0].contents[0]['title']

total_judgement_score = hotel_list[count].findAll("span", { "class" : "total_judgement_score" })[1].get_text()

hotel_judgement = hotel_list[count].find("span", { "class" : "hotel_judgement" }).get_text()

detail_href = hotel_list[count].find("a", { "class" : "btn_buy" })['href']

#构造酒店详情信息的url

detail_url = 'http://hotels.ctrip.com/' + detail_href

try:

#进入酒店详情页面

print '1-------------'

driver.get(detail_url)

print "start new page"

except TimeoutException:

print 'time out after 30 seconds when loading page'

time.sleep(3)

#点击酒店点评

try:

WebDriverWait(driver, 5).until(lambda x: x.find_element_by_id("commentTab")).click()

#程序执行到该处使用driver等待的方式并不能进入超时exception,也不能进入设定好的页面加载超时错误?????

except socket.error:

print 'commtab error'

time.sleep(10)

#driver.execute("acceptAlert") #此行一直出错,浏览器跳出警告框????无法执行任何有关driver 的操作

#continue

#driver.quit()

try:

time.sleep(3)

bar_score = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_xpath("//div[@class='bar_score']"))

except Exception, e:

print 'bbbbbbbbbbbb'

print e

#bar_score = driver.find_element_by_xpath("//div[@class='bar_score']")

#对获取内容进行具体的正则提取

total_score_ptn = re.compile('(.*?)%')

try:

total_score = total_score_ptn.findall(total_judgement_score)[0]

#total_score = total_score_ptn.search(total_judgement_score).group(1)

hotel_sale_ptn = re.compile(r'\d+')

#hotel_sale = hotel_sale_ptnsearch(hotel_judgement).group(1)

hotel_sale = hotel_sale_ptn.findall(hotel_judgement)[0]

except Exception, e:

print 'tote error'

print e

#获取位置、设施、服务、卫生评分

bar_scores_ptn = re.compile(r'\d.\d') #提取字符串中的数字,格式类似于3.4

bar_scores = bar_scores_ptn.findall(bar_score.text)

try:

loc_score = bar_scores[0]

device_score = bar_scores[1]

service_score = bar_scores[2]

clean_score = bar_scores[3]

except Exception, e:

print '0------'

print e

continue

#将每个酒店的所有数据以元祖形式存储进hotel_info,存储成元组是为了方便后面写入excel,

#后将所有酒店信息追加至info_list

hotel_info = (hotel_name,total_score,hotel_sale,loc_score,device_score,service_score,clean_score)

info_list.append(hotel_info)

count += 1

#每一页有25个酒店,每爬取一页显示next page提示,并调用save_score方法存储进excel.

#另外重启浏览器,以防止其崩溃

if count % 24 == 0:

print "next page"

CommentContent().save_score(info_list)

info_list = []

driver.close()

time.sleep(10)

driver = webdriver.Firefox()

except Exception, e:

print 'get detail info error'

#print e

count += 1

continue

#traceback.print_exc()

#driver.close()

break

return info_list

#建立数据存储的excel和格式,以及写入第一行

def build_excel(self):

file = xlwt.Workbook()

sheet1 = file.add_sheet(u'sheet1',cell_overwrite_ok=True)

head_style = xlwt.easyxf('font: name Times New Roman, color-index red, bold on',

num_format_str='#,##0.00')

row0 = ('hotel_name','total_score','sale','loc_score','device_score', 'service_score', 'clean_score')

for i in range(0,len(row0)):

sheet1.write(0,i,row0[i],head_style)

file.save('D:/score1.xls')

#将数据追加至已建立的excel文件中

def save_score(self, info_list):

score_list = info_list

rb_file = xlrd.open_workbook('D:/score.xls')

nrows = rb_file.sheets()[0].nrows #获取已存在的excel表格行数

wb_file = copy(rb_file) #复制该excel

sheet1 = wb_file.get_sheet(0) #建立该excel的第一个sheet副本

try:

for i in range(0,len(score_list)):

for j in range(0,len(score_list[i])):

#将数据追加至已有行后

sheet1.write(i+nrows,j,score_list[i][j])

except Exception, e:

print e

wb_file.save('D:/score1.xls')

print 'save success'

#程序入口

if __name__ == '__main__':

CommentContent().build_excel()

CommentContent().read_hotel()

python 携程_python-携程爬虫相关推荐

  1. python3携程_python携程

    介绍 协程(coroutine),又称为微线程,纤程.协程的作用:在执行A函数的时候,可以随时中断,去执行B函数,然后中断继续执行A函数(可以自动切换),单着一过程并不是函数调用(没有调用语句),过程 ...

  2. python asyncio教程_Python 协程模块 asyncio 使用指南

    Python 协程模块 asyncio 使用指南 前面我们通过5 分钟入门 Python 协程了解了什么是协程,协程的优点和缺点和如何在 Python 中实现一个协程.没有看过的同学建议去看看.这篇文 ...

  3. python gevent缺点_python 协程 greenlet gevent

    一.并发的本质 切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作系统强制控制),一种情况是该任务发生了阻塞,另外一种情况是该任务计算的时间过长时间片到了 二.协程 ...

  4. python协成_Python协程(上)

    几个概念: event_loop 事件循环:程序开启一个无限的循环,程序员会把一些函数注册到事件循环上.当满足事件发生的时候,调用相应的协程函数. coroutine 协程:协程对象,指一个使用asy ...

  5. python使用协程_Python 协程使用心得

    基本概念 协程:又称微线程,纤程.英文名Coroutine.协程是一种子程序,它在执行过程中可以中断,然后转而执行别的子程序,在适当的时候再返回来接着执行. 注意:如程序内不需要中断,则不要定义成协程 ...

  6. python 携程_python 携程爬虫开发笔记

    前言 最近购买了<Python3 爬虫.数据清洗与可视化实战>,刚好适逢暑假,就尝试从携程页面对广州的周边游产品进行爬虫数据捕捉. 因为才学Python不够一个星期,python的命名规范 ...

  7. python从网址爬图片协程_python协程gevent案例 爬取斗鱼图片过程解析

    分析 分析网站寻找需要的网址 用谷歌浏览器摁F12打开开发者工具,然后打开斗鱼颜值分类的页面,如图: 在里面的请求中,最后发现它是以ajax加载的数据,数据格式为json,如图: 圈住的部分是我们需要 ...

  8. python从网址爬图片协程_python协程gevent案例:爬取斗鱼美女图片

    分析 分析网站寻找需要的网址 用谷歌浏览器摁F12打开开发者工具,然后打开斗鱼颜值分类的页面,如图: 在里面的请求中,最后发现它是以ajax加载的数据,数据格式为json,如图: 圈住的部分是我们需要 ...

  9. python 协程_Python 协程与 Go 协程的区别(一)

    ? "Python猫" ,一个值得加星标的公众号 花下猫语:年关将近,不知各位过得怎样?我最近有些忙,收获也挺多,以后有机会分享下.吃饭时间,追了两部剧<了不起的麦瑟尔夫人& ...

  10. python协成_Python协程技术的演进

    引言 1.1. 存储器山 存储器山是 Randal Bryant 在<深入理解计算机系统>一书中提出的概念. 基于成本.效率的考量,计算机存储器被设计成多级金字塔结构,塔顶是速度最快.成本 ...

最新文章

  1. zhlan--Python中的字典遍历方法 字典取值
  2. CTFshow php特性 web111
  3. Open-E DSS V7 应用系列之三 Web管理简介
  4. 聊聊风口上的 eBPF
  5. JavaScript中的一些细节
  6. django 函数装饰器 变为 类装饰器
  7. 统计--过滤(筛选)索引的统计信息过期问题测试
  8. 组合的输出(信息学奥赛一本通-T1317)
  9. 高程数据处理_全国12.5米高程 DEM for WeServer 数据1.0
  10. CCF NOI1075 F函数
  11. 基于Android的人事管理系统开发与设计源码(一)
  12. python征程3.1(列表,迭代,函数,dic,set,的简单应用)
  13. 谷粒学院-第二天笔记
  14. Mac不用Boot Camp 安装双系统
  15. 不用编程,快速实现西门子PLC与罗克韦尔(AB)PLC之间以太网通讯
  16. 蓝牙LMP剖析(一)
  17. 交流电中为什么要用相量法?
  18. 18其他算法(algo)——单纯的数据处理
  19. 使用超声波测距模块控制LED灯
  20. MATLAB实现fplot和ezplot及hist作图【例】

热门文章

  1. SQL 注释语句 (--与/*...*/)
  2. 连自律都做不到 还谈什么梦想
  3. Java读取word模板,并动态生成word
  4. 前端有哪些好的学习网站?
  5. 使用virt-install创建虚拟机
  6. Spring—xml和注解
  7. STATA闪退,CLDS数据无法转码
  8. Qt MetaObject 详解之二:QMeta数据以及数据结构信息
  9. Swift和正则表达式:语法
  10. python_爬虫 16 Scrapy框架之(二)快速入门