总体介绍
- Selenium 简单入门教程
- 使用 Selenium 模拟访问网易数据中心的房价数据
- 使用 Pandas 处理数据
- 使用 Matplotlib 绘制图表
Selenium
安装
- conda install selenium 或 pip install selenium
- 下载浏览器驱动。在 selenium 的 download 页面,Third Party Drivers 处下载对应浏览器驱动,或使用下方链接
- Linux 和 MacOS 用户下载好之后, 将下载好的”geckodriver”文件放在你的计算机的 “/usr/bin” 或 “/usr/local/bin” 目录。并赋予执行权限,如下所示:
sudo cp geckodriver /usr/local/bin
sudo chmod +x /usr/local/bin/geckodriver
windows用户应该是把geckodriver文件放在环境变量中(PATH),详见百度经验。
或者在代码中引用文件所在位置,如下:
from selenium import webdriver
path="D:\\chromedriver.exe" #替换成geckodriver实际所在目录
driver=webdriver.Chrome(path)
driver.get("http://www.yahoo.com")
driver.close()
driver.quit()
安装火狐浏览器插件Katalon Recorder
该组件用于录制用户在浏览器中的操作,并生成python等代码,省去了自己写代码的麻烦。类似按键精灵,可以参考莫烦的视频教程。
- 工具>附加组件>搜索 Katalon Recorder >安装
- 在需要录制的页面打开 Katalon Recorder ,点击录制,然后完成你想录制的操作,点击停止录制,导出代码。例如我在百度搜索框中输入“P2P”,然后点击搜索,录制得到的代码如下:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
class UntitledTestCase(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.katalon.com/"
self.verificationErrors = []
self.accept_next_alert = True
def test_untitled_test_case(self):
driver = self.driver
driver.get("https://www.baidu.com/")
driver.find_element_by_id("kw").click()
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys("P2P")
driver.find_element_by_id("su").click()
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
其中,以下内容是与我们的操作相关的代码
def test_untitled_test_case(self):
driver = self.driver
driver.get("https://www.baidu.com/") #打开百度搜索页面
driver.find_element_by_id("kw").click() #点击搜索输入框,这个在写代码时可以不要
driver.find_element_by_id("kw").clear() #清空里面已有的输入
driver.find_element_by_id("kw").send_keys("P2P") #在里面输入P2P搜索词
driver.find_element_by_id("su").click() #点击搜索按钮
后台运行
- 安装PhantomJs,见参考链接
- driver = webdriver.PhantomJS()
简单教程
- 连接浏览器,以火狐Firefox浏览器为例
from selenium import webdriver
self.driver = webdriver.Firefox()
- 打开某个页面
driver.get("https://www.baidu.com/")
- 等待具有某个ID的元素加载完成,这用来保证页面以及加载出来
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "kw"))) #这是百度输入框的ID
获取输入框ID可以使用Firefox或Chrome浏览器的提供的调试工具,对于Firefox浏览器,在页面右键选择“查看元素”即可打开调试页面,点击调试页面左上角的“选择一个元素”按钮,再点击百度的输入框,可以在下方看到它的ID为“kw”
- 使用前面我们录制得到的代码实现自动输入搜索词
driver.find_element_by_id("kw").clear() #清空里面已有的输入
driver.find_element_by_id("kw").send_keys("P2P") #在里面输入P2P搜索词
driver.find_element_by_id("su").click() #点击搜索按钮
- 通过“审查元素”分析,我们发现百度搜索得到的每个词条的
class属性都为result c-container,通过这个,我们可以得到所有搜索结果
e_item = driver.find_elements_by_xpath('//div[@class="result c-container "]')
print('\n'.join([e.find_element_by_tag_name('a').text for e in e_item])) #打印每个条目的内容
结果如下:
【网贷之家】中国首家权威p2p网贷投资理财行业门户_网贷理财_p2p…
P2P平台被清盘后,你会怎样捍卫自身利益?
P2P金融_百度百科
P2psearcher绿色版下载_P2psearcher免安装版官方下载-华军软件园
国家出手,P2P现回暖迹象!
迪蒙–供应链金融、黄金理财、融资租赁、消费金融系统专业开发商
同样,我们也可以获得每个条目的链接,进入链接即可抓取我们想要的数据
print('\n'.join([e.find_element_by_tag_name('a').get_attribute('href') for e in e_item]))
结果如下:
http://www.baidu.com/link?url=80_XPZ-NHHGGwNmIpG5kNuAn0b8MKU5rHrdy-dJXwvy
http://www.baidu.com/link?url=Vik9gXKc-hz-tGHQ1JcsRVzCn7vXRMr_HXNuuYa_sc_4o_Epq6Z7v7rZeW070Orxr3rWtAnAz44FR9vZSDtzcykS7WzmdI_JGfml2jERU
http://www.baidu.com/link?url=sq7r9PEl1YjbGpDFNQKauiE21G7wKHYK9PpL1gRG6j6OPEpPrDXmTVbaO0ExdCoevQVaZzjqbvm0Pe_c1p_DHigIukY5n_-yr784N6ulcQC
http://www.baidu.com/link?url=tXD8qkEJClA6bqXKjIq0Zg9gICFvKaC6QgCpE1FGn1xnXXd_8UAfGrNRLvH1cX-PMdkJ15mhnMUJzld1R_-vc_
http://www.baidu.com/link?url=Jd1r4dPGnyYHxC9VuhtzWQFV3-Je4WzLC0UZJqdMJQT1ExBYOuBDI5mpRKDIT5lV564GTSe1Xw_3ZRqxjVI6UDU0SKh-spSslgiLGgsie0C
http://www.baidu.com/link?url=ONtuKqNGH5M2PCqcEJ9AuQMLfWpoq8KTVMmY9mKLjya
- 抓完一页的结果之后,再翻到下一页
driver.find_element_by_xpath(u"//div[@id='page']/descendant::span[text()='2']").click() #其中2为页码,可以依次换成其他页码
- 完整代码如下:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
driver = webdriver.Firefox()
driver.get("https://www.baidu.com")
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "kw")))
driver.find_element_by_id("kw").clear() #清空里面已有的输入
driver.find_element_by_id("kw").send_keys("P2P") #在里面输入P2P搜索词
driver.find_element_by_id("su").click() #点击搜索按钮
for i in range(2,5,1):
time.sleep(1)
e_item = driver.find_elements_by_xpath('//div[@class="result c-container "]')
print('\n'.join([e.find_element_by_tag_name('a').text for e in e_item]))
driver.find_element_by_xpath(f"//div[@id='page']/descendant::span[text()='{i}']").click()
driver.quit()
结果如下:
【网贷之家】中国首家权威p2p网贷投资理财行业门户_网贷理财_p2p…
P2P金融_百度百科
P2psearcher绿色版下载_P2psearcher免安装版官方下载-华军软件园
P2P | 异次元软件世界
迪蒙–供应链金融、黄金理财、融资租赁、消费金融系统专业开发商
P2P“大崩盘”:上百家平台爆雷 众多投资人卷入其中|P2P…_新浪科技
一周40家P2P“爆雷”,一旦踩雷就血本无归? | 小巴问大…_搜狐财经
p2p有哪些公司_网贷天眼
P2P“大崩盘”:上百家平台爆雷 众多投资人卷入其中|P2P…_新浪科技
世上再无P2P-虎嗅网
网贷天眼-你的互联网金融理财助手_P2P网贷理财
互联网p2p理财网贷平台_P2P投资理财专家_现金万家P2P投资理财网
半个月超40家平台"爆雷" P2P行业发生了什么事_网易科技
【你我贷官网】平稳运营7年有余的P2P网络借贷信息中介平台,网上…
一天17个P2P平台出问题?起码一半存在
p2p什么时候进入中国的_网贷天眼
红岭创投_值得信赖的P2P网贷平台_P2P个人理财平台
红岭创投_值得信赖的P2P网贷平台_P2P个人理财平台
对等网络_百度百科
P2P 是什么? - 知乎
频频爆雷背后暴露三大原因 P2P网贷行业该走向何方?互联网金融…
P2P理财_P2P理财排名_P2P网贷平台 - 融360
P2P网贷|P2P理财|P2P贷款 - 专业的P2P网贷产品导购平台_希…_希财
富金利_P2P平台_专业安全的P2P网贷投融资平台【唯一官网】
P2P - 金评媒
p2p吧-百度贴吧
P2P | 人人都是产品经理
抓取网易房地产数据例子
# -*- coding: utf-8 -*-
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions
import unittest, time, re
import pandas as pd
class MyCrawler(object):
def __init__(self):
self.path = "/home/liucc/Workspace/Housing/data"
if not os.path.exists(self.path):
os.mkdir(self.path)
self.driver = webdriver.Firefox()
self.base_url = "http://data.house.163.com/bj/housing/trend/district/todayprice/{date:s}/{interval:s}/allDistrict/1.html?districtname={disname:s}#stoppoint"
self.data = None
def craw_page(self,date="2014.01.01-2018.09.15",interval="month",disname="全市"):
driver = self.driver
url = self.base_url.format(date=date,interval=interval,disname=disname)
print('访问网址:'+url)
driver.get(url)
try:
# we have to wait for the page to refresh, the last thing that seems to be updated is the title
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "resultdiv_1")))
print(driver.title)
self.data = pd.DataFrame()
ct = True
while ct:
self.get_items_in_page(driver)
e_pages = driver.find_elements_by_xpath('//div[@class="pager_box"]/a[@class="pager_b current"]/following::a[@class="pager_b "]')
if len(e_pages)>0:
next_page_num = e_pages[0].text
e_pages[0].click()
#通过判断当前页是否为我们点击页面的方式来等待页面加载完成
WebDriverWait(driver, 10).until(
expected_conditions.text_to_be_present_in_element(
(By.XPATH, '//a[@class="pager_b current"]'),
next_page_num
)
)
else:
ct = False
break
return self.data
finally:
driver.quit()
def get_items_in_page(self,driver):
e_tr = driver.find_elements_by_xpath("//tr[normalize-space(@class)='mBg1' or normalize-space(@class)='mBg2']")
temp = pd.DataFrame(e_tr,columns=['web'])
temp['时间']=temp.web.apply(lambda x:x.find_element_by_class_name('wd2').text.split(' ')[0])
temp['套数']=temp.web.apply(lambda x:x.find_element_by_class_name('wd5').text)
temp['均价']=temp.web.apply(lambda x:x.find_element_by_class_name('wd7').text)
temp['去化']=temp.web.apply(lambda x:x.find_element_by_class_name('wd14').text)
del temp['web']
self.data = pd.concat([temp,self.data],axis=0)
mcraw = MyCrawler()
data = mcraw.craw_page()
访问网址:http://data.house.163.com/bj/housing/trend/district/todayprice/2014.01.01-2018.09.15/month/allDistrict/1.html?districtname=全市#stoppoint
北京全市-住宅-成交均价住宅成交数据_北京房价_网易北京房产
data= data.sort_values(by='时间')
print(data.to_string(index=False))
时间 套数 均价 去化
2014-01 4040 28,012 40.8%
2014-02 1302 26,990 40.5%
2014-03 4939 28,330 40.3%
2014-04 3388 26,372 39.4%
2014-05 3499 26,592 38.8%
2014-06 2780 28,627 59.8%
2014-07 3969 25,539 59.7%
2014-08 5221 24,814 59.6%
2014-09 3563 26,199 59.5%
2014-10 6554 23,045 59.7%
2014-11 8133 24,122 60.0%
2014-12 9337 25,287 59.8%
2015-01 7614 28,280 60.2%
2015-02 2750 23,755 60.3%
2015-03 2895 26,832 60.4%
2015-04 5341 25,460 60.5%
2015-05 5347 27,486 60.8%
2015-06 5634 30,185 60.9%
2015-07 9915 27,662 61.0%
2015-08 7475 28,371 61.4%
2015-09 5698 29,887 61.6%
2015-10 6205 26,145 61.8%
2015-11 4944 32,372 61.9%
2015-12 9451 29,368 62.3%
2016-01 4030 31,019 62.5%
2016-02 1886 33,160 62.6%
2016-03 4209 37,005 62.9%
2016-04 5245 36,337 63.2%
2016-05 4565 37,107 63.4%
2016-06 4400 37,236 63.4%
2016-07 6559 34,711 63.5%
2016-08 6895 32,322 63.6%
2016-09 4865 40,565 63.8%
2016-10 3747 40,285 64.3%
2016-11 2092 44,213 64.4%
2016-12 4210 41,741 64.5%
2017-01 2432 41,857 64.6%
2017-02 2308 42,876 64.6%
2017-03 2491 42,795 64.7%
2017-04 2471 45,886 64.8%
2017-05 2666 44,751 64.9%
2017-06 1812 48,792 64.9%
2017-07 1895 51,526 64.9%
2017-08 1577 47,958 64.9%
2017-09 1270 56,663 64.9%
2017-10 1340 55,968 64.8%
2017-11 2625 46,608 64.8%
2017-12 2748 53,320 64.8%
2018-01 1615 42,206 64.7%
2018-02 1138 42,280 64.7%
2018-03 1243 42,498 64.6%
2018-04 1408 46,897 64.6%
2018-05 3560 43,199 64.8%
2018-06 1884 43,391 64.9%
2018-07 2090 47,960 64.9%
2018-08 4181 41,096 65.0%
2018-09 2369 31,965 65.1%
data.to_csv('./data/housing_beijing.csv',index=False)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 指定默认字体
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['font.family']='sans-serif'
# 用来正常显示负号
plt.rcParams['axes.unicode_minus']=False
data = pd.read_csv('./data/housing_beijing.csv')
y = [float(s.replace(',','')) for s in data['均价'].values]
plt.plot(y,color='red', marker='o', linestyle='solid')
plt.xlabel(u'日期')
plt.ylabel(u'均价(元)')
plt.title(u'北京房价走势')
plt.show()

matplotlib中文乱码的解决详见参考链接