使用selenium的爬虫更加像一个人能够做人为的点击滑动等操作。
在一次爬虫中遇到了xx文库这种,非静态网页,不能一次请求遍获取全部数据,后查询selenium能完成点击滑动等动态操作
1.库准备
selenium
BeautifulSoup
re
time
在使用selenium时需配合本机的浏览器版本下载对应的驱动最常用的两个谷歌和搜狐的驱动器,可网上百度下载安装。
2.构建浏览器实列,模拟人为点击与滑动。某某文库的文档是只能浏览部分,需要点击浏览更多才能加载出后面未显示的内容。
在浏览器中进入开发者模式找到如上图所示的对象,选择他上方(或下方适应位置的对象),复制类选择器,通过browser.find_element_by_css_selector()寻找对象,后使用browser.execute_script("arguments[0].scrollIntoView();", scroll_add_crowd_button)定位元素到视窗中,scrollIntoView()中默然参数为true,即目标元素与视窗顶部对齐,若为false则目标元素与底部对齐。因为上或下对齐,xx文库的视窗中都有顶层元素覆盖,不能点击到想要的元素,所以选取上(或下)适应元素将目标元素定位到视窗中位置,若目标元素不在视图中也不能点击。
#构建一个浏览器,并请求网页
browser = webdriver.Chrome()
url = 'https://wenku.baidu.com/view/f15a777a27284b73f242507f.html'
browser.get(url)
#等待页面加载完成,否则可能出现找不到目标元素或不能点击等情况
time.sleep(5)
#找到目标元素上方适应位置的元素
scroll_add_crowd_button = browser.find_element_by_css_selector('#html-reader-go-more > div.banner-core-wrap.super-vip > div.doc-banner-text')
#滚动视图到与上方元素对齐的位置
browser.execute_script("arguments[0].scrollIntoView();", scroll_add_crowd_button)
time.sleep(1)
#使用selenium的点击,等待加载
try:
browser.find_element_by_css_selector('div.continue-to-read > div.banner-more-btn > span').click()
time.sleep(5)
except Exception as e:
print(str(e))
3.使用selenium点击“阅读更多”之后加载完成隐藏的数据,循环滚动滚动条,让页面加载每一页的数据(该页面共27页,每次html只加载当前页前后两页的数据),滚动一次保存html 添加进string变量,最后对string解析把解析出来的数据转为set去重。
html = ''
a = 0
#循环滚动滚动条到下一页,每一次滚动都把html加到string类型的html中
while True:
a += 1
html = html + browser.page_source
browser.execute_script("window.scrollBy(0, 1050)")
time.sleep(1)
if a >= 27:
break
#html解析整理数据
soup = BeautifulSoup(html, 'html.parser')
data_list = soup.select('div.reader-txt-layer > div.ie-fix > p')
print(data_list)
a = 0
b = 0
c = 0
data_all = []
data_line = []
for i in data_list:
a = a+1
data = i.find_all(text=True)[0]
data_line.append(data)
rese_number = re.compile('\d+')
if rese_number.search(data):
b += 1
s = ','.join(data_line).replace('\n','')
data_all.append(s)
data_line = []
print(s + "_____" + str(b))
rese = re.compile('\n')
if rese.search(data):
c += 1
print('共' + c + '条数据。')
#多次保存html造成数据重复,通过set去重
data_all = set(data_all)