目录
四、爬虫数据存储csv/excel
六、selenium库:控制浏览器操作
七、定时与邮件
上一篇爬虫操作基础,本篇讲解爬虫数据存储、cookies,session,以及浏览器自动操作工具selenium
爬虫操作比较完整的步骤如下图所示:
总体上来说,从Response对象开始,我们就分成了两条路径,一条路径是数据放在HTML里,所以我们用BeautifulSoup库去解析数据和提取数据;另一条,数据作为Json存储起来,所以我们用response.json()方法去解析,然后提取、存储数据。
csv为python自带模块,无需安装。
csv基本操作步骤:
打开文件——>读取数据/写入数据——>关闭文件
示例如下:
# CSV存储示例
import csv
with open('test.csv','a', newline='',encoding='utf-8') as f:
writer = csv.writer(f)
#['4', '猫砂', '25', '1022', '886']
#['5', '猫罐头', '18', '2234', '3121']
writer.writerow(['4', '猫砂', '25', '1022', '886'])
writer.writerow(['5', '猫罐头', '18', '2234', '3121'])
# CSV读取示例
with open('test.csv','r', newline='',encoding='utf-8') as f:
read = csv.reader(f)
for row in read:
print(row)
excel操作可以使用openpyxl,为第三方库,需按照:pip install openpyxl
Excel文件写入步骤:
1、创建工作簿:利用openpyxl.Workbook()创建workbook对象;
2、获取工作表:借助workbook对象的avtive属性;
3、操作单元格:单元格:sheet['A1'];一行:append();
4、保存工作簿:save().
# xlsx表格存储示例
from openpyxl import Workbook
wb = Workbook() #建立工作簿
ws = wb.active
ws.title #打印title
# ‘Sheet’
ws.title = 'python' #改变sheet title
ws.title
# 'python'
ws2 = wb.create_sheet('java') #新建工作表
ws2.title
# 'java'
wb.sheetnames
# ['python','java']
ws['E1'] = 111 #向E1单元写入数据
ws.cell(row=2,column=2,value=222) #向第二行第二列的单元格写入数据
#
wb.save('example.xlsx') #保存excel表格 |
1、session与cookies联系
session和cookies的关系还非常密切——cookies中存储着session的编码信息,session中又存储了cookies的信息。
当浏览器第一次访问购物网页时,服务器会返回set cookies的字段给浏览器,而浏览器会把cookies保存到本地。
等浏览器第二次访问这个购物网页时,就会带着cookies去请求,而因为cookies里带有会话的编码信息,服务器立马就能辨认出这个用户,同时返回和这个用户相关的特定编码的session。
流程如下图所示:
cookies和session的关系如此密切,那我们可以通过创建一个session来处理cookies。
计算机之所以需要cookies和session,是因为HTTP协议是无状态的协议。
何为无状态?就是一旦浏览器和服务器之间的请求和响应完毕后,两者会立马断开连接,也就是恢复成无状态。
这样会导致:服务器永远无法辨认,也记不住用户的信息,像一条只有7秒记忆的金鱼。是cookies和session的出现,才破除了web发展史上的这个难题。
cookies不仅仅能实现自动登录,因为它本身携带了session的编码信息,网站还能根据cookies,记录你的浏览足迹,从而知道你的偏好,只要再加以推荐算法,就可以实现给你推送定制化的内容。
2、post请求:
post和get都可以带着参数请求,不过get请求的参数会在url上显示出来。但post请求的参数就不会直接显示,而是隐藏起来。像账号密码这种私密的信息,就应该用post的请求。如果用get请求的话,账号密码全部会显示在网址上。可以这么理解,get是明文显示,post是非明文显示。
通常,get请求会应用于获取网页数据,比如我们之前学的requests.get()。post请求则应用于向网页提交数据,比如提交表单类型数据(像账号密码就是网页表单的数据)。
【requests headers】存储的是浏览器的请求信息,【response headers】存储的是服务器的响应信息
一般post操作重点:
1、post带着参数地请求登录;
2、获得登录的cookies;
3、带cookies去请求发送信息;
3、cookies存储与提取
1) cookies
cookies转化成字典的方法
requests对于cookies格式的转化,提供了三个工具方法:
requests.utils.dict_from_cookiejar(cj)
Returns a key/value dictionary from a CookieJar.
Parameters: cj – CookieJar object to extract cookies from.
requests.utils.cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)
Returns a CookieJar from a key/value dictionary.
Parameters:
cookie_dict – Dict of key/values to insert into CookieJar.
cookiejar – (optional) A cookiejar to add the cookies to.
overwrite – (optional) If False, will not replace cookies already in the jar with new ones.
requests.utils.add_dict_to_cookiejar(cj, cookie_dict)
Returns a CookieJar from a key/value dictionary.
Parameters:
cj – CookieJar to insert cookies into.
cookie_dict – Dict of key/values to insert into CookieJar.
json模块的使用方法:
但都是cookiejar和字典格式之间的转换,并没有几种cookies格式相互的转换,所以我是以字典为中间格式进行转换的。
2)读取cookies
在这里我用的是LWPCookieJar保存在txt文件中
#实例化一个LWPCookieJar对象
load_cookiejar = cookielib.LWPCookieJar()
#从文件中加载cookies(LWP格式)
load_cookiejar.load('cookies/' + self.username + '.txt', ignore_discard=True, ignore_expires=True)
#工具方法转换成字典
load_cookies = requests.utils.dict_from_cookiejar(load_cookiejar)
#工具方法将字典转换成RequestsCookieJar,赋值给session的cookies.
self.session.cookies = requests.utils.cookiejar_from_dict(load_cookies)
3)存储cookies
将cookies转换成LWP格式然后保存为文本格式
#实例化一个LWPcookiejar对象
new_cookie_jar = cookielib.LWPCookieJar(self.username + '.txt')
#将转换成字典格式的RequestsCookieJar(这里我用字典推导手动转的)保存到LWPcookiejar中
requests.utils.cookiejar_from_dict({c.name: c.value for c in self.session.cookies}, new_cookie_jar)
#保存到本地文件
new_cookie_jar.save('cookies/' + self.username + '.txt', ignore_discard=True, ignore_expires=True)
4)完整示例
import requests, json
session = requests.session()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'}
def cookies_read():
cookies_txt = open('cookies.txt', 'r')
cookies_dict = json.loads(cookies_txt.read())
cookies = requests.utils.cookiejar_from_dict(cookies_dict)
return (cookies)
# 以上4行代码,是cookies读取。
def sign_in():
url = ' https://wordpress-edu-3autumn.localprod.oc.forchange.cn/wp-login.php'
data = {'log': input('请输入你的账号'),
'pwd': input('请输入你的密码'),
'wp-submit': '登录',
'redirect_to': 'https://wordpress-edu-3autumn.localprod.oc.forchange.cn',
'testcookie': '1'}
session.post(url, headers=headers, data=data)
cookies_dict = requests.utils.dict_from_cookiejar(session.cookies)
cookies_str = json.dumps(cookies_dict)
f = open('cookies.txt', 'w')
f.write(cookies_str)
f.close()
# 以上5行代码,是cookies存储。
def write_message():
url_2 = 'https://wordpress-edu-3autumn.localprod.oc.forchange.cn/wp-comments-post.php'
data_2 = {
'comment': input('请输入你要发表的评论:'),
'submit': '发表评论',
'comment_post_ID': '13',
'comment_parent': '0'
}
return (session.post(url_2, headers=headers, data=data_2))
#以上9行代码,是发表评论。
try:
session.cookies = cookies_read()
except FileNotFoundError:
sign_in()
num = write_message()
if num.status_code == 200: #解决cookies过期的问题,如果过期则重新登入
print('成功啦!')
else:
sign_in()
num = write_message()
print(num.status_code)
selenium是什么呢?它是一个强大的Python库。
它可以做什么呢?它可以用几行代码,控制浏览器,做出自动打开、输入、点击等操作,就像是有一个真正的用户在操作一样。
selenium操作步骤:
1、安装selenium
pip install selenium
2、下载谷歌浏览器chrome,安装对应版本浏览器驱动ChromeDriver
https://www.google.cn/intl/zh-CN/chrome/
http://npm.taobao.org/mirrors/chromedriver/
https://localprod.pandateacher.com/python-manuscript/crawler- html/chromedriver/ChromeDriver.html
3、浏览器设置
# 本地Chrome浏览器设置方法(打开一个真实的浏览器界面)
from selenium import webdriver #从selenium库中调用webdriver模块
driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器
# 本地Chrome浏览器的静默默模式设置(不显示浏览器界面,后台运行):
from selenium import webdriver #从selenium库中调用webdriver模块
from selenium.webdriver.chrome.options import Options # 从options模块中调用Options类
chrome_options = Options() # 实例化Option对象
chrome_options.add_argument('--headless') # 把Chrome浏览器设置为静默模式
driver = webdriver.Chrome(options = chrome_options) # 设置引擎为Chrome,在后台默默运行
4、selenium数据提取
BeautifulSoup解析网页源代码,然后提取其中的数据。
selenium库同样也具备解析数据、提取数据的能力。它和BeautifulSoup的底层原理一致,但在一些细节和语法上有所出入selenium所解析提取的,是Elements中的所有数据,而BeautifulSoup所解析的则只是Network中第0个请求的响应。
使用BeautifulSoup解析提取数据时,首先要把Response对象解析为BeautifulSoup对象,然后再从中提取数据。
而在selenium中,获取到的网页存在了driver中,而后,解析与提取是同时做的,都是由driver这个实例化的浏览器完成,解析数据是由driver自动完成的,提取数据是driver的一个方法。
selenium解析与提取数据的过程中,我们操作的对象转换:
selenium可以获取到渲染完整的网页源代码。
使用driver的一个方法:page_source
HTML源代码字符串 = driver.page_source
用requests.get()获取到的是Response对象,在交给BeautifulSoup解析之前,需要用到.text的方法才能将Response对象的内容以字符串的形式返回。
而使用selenium获取到的网页源代码,本身已经是字符串了。可以直接交给BeautifulSoup进行解析。
5、selenium自动操作浏览器
完整示例:
# 本地Chrome浏览器设置方法
from selenium import webdriver #从selenium库中调用webdriver模块
import time
from bs4 import BeautifulSoup
driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器
#driver是浏览器驱动的实例化对象
driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/')
time.sleep(2)
#操作浏览器
# teacher = driver.find_element_by_id('teacher')
# teacher.send_keys('必须是吴枫呀')
# assistant = driver.find_element_by_name('assistant')
# assistant.send_keys('都喜欢')
# time.sleep(1)
# button = driver.find_element_by_class_name('sub')
# time.sleep(1)
# button.click()
# time.sleep(1)
# driver.close()
# 提取出网页 你好,蜘蛛侠! 中所有label标签中的文字
#方法一:
# labels = driver.find_elements_by_tag_name('label')
# labels = BeautifulSoup.find_all('label')
# for label in labels:
# print(label.text)
# driver.close()
#方法二:selenium + BeautifulSoup
html = driver.page_source
html_soup = BeautifulSoup(html,'html.parser')
labels = html_soup.find_all('label')
for label in labels:
print(label.text)
driver.close()
#刷新页面
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(6)
driver.get("https://www.baidu.com")
time.sleep(2)
try:
driver.refresh() # 刷新方法 refresh
print ('test pass: refresh successful')
except Exception as e:
print ("Exception found", format(e))
driver.quit()
Selenium是一个强大的网络数据采集工具,它的优势是简单直观,而它当然也有缺点。由于是真实地模拟人操作浏览器,需要等待网页缓冲的时间,在爬取大量数据的时候,速度会比较慢。通常情况,在爬虫项目中,selenium都是用在其它方法无法解决,或是很难解决的问题时,才会用到。
当然,除了爬虫,selenium的使用场景还有很多。比如:它可以控制网页中图片文件的显示、控制CSS和JavaScript的加载与执行等等。
1、邮件发送步骤:
2、定时
关于时间,其实Python有两个内置的标准库——time和datetime(我们在基础课也学过time.sleep())。
但在这里,我们不准备完全依靠标准库来实现,而准备选取第三方库——schedule。
标准库一般意味着最原始最基础的功能,第三方库很多是去调用标准库中封装好了的操作函数。比如schedule,就是用time和datetime来实现的。
完整示例:
#@ description :爬虫+邮件定时发送实战:定时发送天气信息
# 自动爬取每日的天气,并定时把天气数据和穿衣提示发送到你的邮箱
# http://www.weather.com.cn/weather/101280601.shtml
#@ Author :Dannie
#@ time :2020/08/09 23:02:02
#@ version :V1.0
#********************#
import requests
import smtplib
import schedule
import time
from bs4 import BeautifulSoup
from email.mime.text import MIMEText
from email.header import Header
account = input('请输入你的邮箱:')
password = input('请输入你的密码:')
receiver = input('请输入收件人的邮箱:')
def weather_spider():
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
url='http://www.weather.com.cn/weather/101280601.shtml'
res=requests.get(url,headers=headers)
res.encoding='utf-8'
soup=BeautifulSoup(res.text,'html.parser')
tem1= soup.find(class_='tem')
weather1= soup.find(class_='wea')
tem=tem1.text
weather=weather1.text
return tem,weather
def send_email(tem,weather):
mailhost='smtp.qq.com'
qqmail = smtplib.SMTP()
qqmail.connect(mailhost,25)
qqmail.login(account,password)
content= tem+weather
message = MIMEText(content, 'plain', 'utf-8')
subject = '今日天气预报'
message['Subject'] = Header(subject, 'utf-8')
try:
qqmail.sendmail(account, receiver, message.as_string())
print ('邮件发送成功')
except:
print ('邮件发送失败')
qqmail.quit()
def job():
print('开始一次任务')
tem,weather = weather_spider()
send_email(tem,weather)
print('任务完成')
schedule.every().day.at("07:30").do(job)
while True:
schedule.run_pending()
time.sleep(1)