1、爬取整个网页源码
1. main()
if __name__ == "__main__":
kw = raw_input("请输入需要爬取的贴吧名:")
beginPage = int(raw_input("请输入起始页:"))
endPage = int(raw_input("请输入结束页:"))
url = "http://tieba.baidu.com/f?"
key = urllib.urlencode({"kw": kw})
fullurl = url + key
tiebaSpider(fullurl, beginPage, endPage)
2. tiebaSpider() 爬虫入口
def tiebaSpider(url, beginPage, endPage):
"""
作用:贴吧爬虫调度器,负责组合处理每个页面的url
url : 贴吧url的前部分
beginPage : 起始页
endPage : 结束页
"""
for page in range(beginPage, endPage + 1):
pn = (page - 1) * 50 # page_num 获取哪一页的数据
filename = "第" + str(page) + "页.html"
fullurl = url + "&pn=" + str(pn) # 构造获取哪一页数据的完整url
#print fullurl
html = loadPage(fullurl, filename) # 调用loadPage()下载该页的网页源码
#print html
writePage(html, filename) # 将获取的网页源码写入到本地文件
print "谢谢使用"
3. loadPage() 读取网页源码
def loadPage(url, filename):
"""
作用:根据url发送请求,获取服务器响应文件
url: 需要爬取的url地址
filename : 处理的文件名
"""
print "正在下载 " + filename
headers = {"User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"}
request = urllib2.Request(url, headers = headers)
return urllib2.urlopen(request).read()
4. writePage() 写入本地文件
def writePage(html, filename):
"""
作用:将html内容写入到本地
html:服务器相应文件内容
"""
print "正在保存 " + filename
# 文件写入
with open(filename, "w") as f:
f.write(html)
print "-" * 30
5. 完整代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
# 1、读取url对应的网页源码字符串
def loadPage(url, filename):
"""
作用:根据url发送请求,获取服务器响应文件
url: 需要爬取的url地址
filename : 处理的文件名
"""
print "正在下载 " + filename
headers = {"User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"}
request = urllib2.Request(url, headers = headers)
return urllib2.urlopen(request).read()
# 2、将读取到的网页源码字符串,写入到本地文件
def writePage(html, filename):
"""
作用:将html内容写入到本地
html:服务器相应文件内容
"""
print "正在保存 " + filename
# 文件写入
with open(filename, "w") as f:
f.write(html)
print "-" * 30
# 3、爬虫入口程序
def tiebaSpider(url, beginPage, endPage):
"""
作用:贴吧爬虫调度器,负责组合处理每个页面的url
url : 贴吧url的前部分
beginPage : 起始页
endPage : 结束页
"""
for page in range(beginPage, endPage + 1):
pn = (page - 1) * 50 # page_num 获取哪一页的数据
filename = "第" + str(page) + "页.html"
fullurl = url + "&pn=" + str(pn) # 构造获取哪一页数据的完整url
#print fullurl
html = loadPage(fullurl, filename) # 调用loadPage()下载该页的网页源码
#print html
writePage(html, filename) # 将获取的网页源码写入到本地文件
print "谢谢使用"
# 4、main()
if __name__ == "__main__":
kw = raw_input("请输入需要爬取的贴吧名:")
beginPage = int(raw_input("请输入起始页:"))
endPage = int(raw_input("请输入结束页:"))
url = "http://tieba.baidu.com/f?"
key = urllib.urlencode({"kw": kw})
fullurl = url + key
tiebaSpider(fullurl, beginPage, endPage)
2、正则匹配获取想要的数据
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib2
import re
class Spider:
def __init__(self):
# 初始化起始页位置
self.page = 1
# 爬取开关,如果为True继续爬取
self.switch = True
def loadPage(self):
"""
作用:下载页面
"""
# 发送网络请求获取某一页的json数据
url = "http://www.neihan8.com/article/list_5_" + str(self.page) + ".html"
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
request = urllib2.Request(url, headers = headers)
response = urllib2.urlopen(request)
# 获取每页的HTML源码字符串
html = response.read()
#print html
# 创建正则表达式规则对象,匹配每页里的段子内容,re.S 表示匹配全部字符串内容
pattern = re.compile('(.*?)', re.S)
# 将正则匹配对象应用到html源码字符串里,返回这个页面里的所有段子的列表
content_list = pattern.findall(html)
# 调用dealPage() 处理段子里的杂七杂八
self.dealPage(content_list)
def dealPage(self, content_list):
"""
处理每页的段子
content_list : 每页的段子列表集合
"""
for item in content_list:
# 将集合里的每个段子按个处理,替换掉无用数据
item = item.replace("","").replace("
", "").replace("
", "")
#print item.decode("gbk")
# 处理完后调用writePage() 将每个段子写入文件内
self.writePage(item)
def writePage(self, item):
"""
把每条段子逐个写入文件里
item: 处理后的每条段子
"""
# 写入文件内
print "正在写入数据...."
with open("duanzi.txt", "a") as f:
f.write(item)
def startWork(self):
"""
控制爬虫运行
"""
# 循环执行,直到 self.switch == False
while True:
# 用户确定爬取的次数
self.loadPage()
command = raw_input("如果继续爬取,请按回车(退出输入quit)")
# 如果停止爬取,则输入 quit
if command == "quit":
break
# 每次循环,page页码自增1
self.page += 1
if __name__ == "__main__":
duanziSpider = Spider()
duanziSpider.startWork()
3、网页截图
首先需要安装如下2个py库
- 1、Selenium 页面自动化测试
- 2、PhantomJS 没有界面的浏览器
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from selenium import webdriver
import time
url = "https://movie.douban.com/typerank?type_name=剧情&type=11&interval_id=100:90&action="
# 1.
driver = webdriver.PhantomJS()
driver.get(url)
# 2. 对当前页面进行截图
driver.save_screenshot("douban.png")
time.sleep(3)
# 3. 让页面向下滚动10000像素
js = "document.body.scrollTop=10000"
#js="var q=document.documentElement.scrollTop=10000"
driver.execute_script(js) # 执行JS语句
time.sleep(10)
# 4. 对当前页面进行截图
driver.save_screenshot("newdouban.png")
# 5.
driver.quit()
4、验证码
调用服务器api生成验证码,然后手动输入验证码后走后续流程
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
import requests
import time
# - 将获取到的验证码图片二进制数据,写入到本地文件
# - 手动打开写入本地的captcha.jpg图片,查看对应的验证码
# - 输入查看到的验证码,作为后续网络请求的参数
def captcha(image_data):
# 1、写入图片到本地
with open("captcha.jpg", "wb") as f:
f.write(image_data)
# 2、等待手动打开图片查看验证码并输入
text = raw_input("请输入验证码:")
# 3、返回用户输入的验证码
return text
def zhihuLogin():
# 1、构建一个Session对象,可以保存页面Cookie
sess = requests.Session()
# 2、请求报头
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
# 3、首先获取登录页面,找到需要POST的数据(_xsrf),同时会记录当前网页的Cookie值
html = sess.get("https://www.zhihu.com/#signin", headers = headers).text
# 4、调用lxml解析库,解析html页面数据
bs = BeautifulSoup(html, "lxml")
# 5、找到name属性值为 _xsrf 的input标签,再取出value 的值
#
# _xsrf作用:
# - 1) 是防止CSRF攻击(跨站请求伪造),通常叫跨域攻击,是一种利用网站对用户的一种信任机制来做坏事
# - 2) 跨域攻击通常通过伪装成网站信任的用户的请求(利用Cookie),盗取用户信息、欺骗web服务器
# - 3) 所以网站会通过设置一个隐藏字段来存放这个MD5字符串,这个字符串用来校验用户Cookie和服务器Session的一种方式
_xsrf = bs.find("input", attrs={"name":"_xsrf"}).get("value")
# 6、根据UNIX时间戳,构造获取验证码图片的链接
#
# In [1]: import time
# In [2]: time.time()
# Out[2]: 1516071313.614512
# In [3]: time = time.time()
# In [4]: time = time * 1000
# In [6]: print(time)
# 1516071327510.68
# In [7]: print("%d"%(time))
# 1516071327510
#
# 最终得到的1516071327510就是知乎获取时间戳对应的验证码图片的参数r的值
captcha_url = "https://www.zhihu.com/captcha.gif?r=%d&type=login" % (time.time() * 1000)
# 7、发送图片的请求,获取图片字节流数据
captcha_data = sess.get(captcha_url, headers = headers).content
# 8、等待手动输入验证码图片中的验证码字符串
text = captcha(captcha_data)
# 9、构造后续调用服务器api的post参数字典
data = {
"_xsrf" : _xsrf,
"email" : "[email protected]",
"password" : "ALARMCHIME",
"captcha" : text
}
# 10、发送登录需要的POST数据,获取登录后的Cookie(保存在sess里)
response = sess.post("https://www.zhihu.com/login/email", data = data, headers = headers)
#print response.text
# 11、用已有登录状态的Cookie发送请求,获取需要【登录态】才能显示的页面源码
response = sess.get("https://www.zhihu.com/people/maozhaojun/activities", headers = headers)
with open("my.html", "w") as f:
f.write(response.text.encode("utf-8"))
if __name__ == "__main__":
zhihuLogin()
- 1、首先搞清楚服务器生成验证码的方法
- 2、获取页面 xsrf 跨站攻击随机数,作为【请求头参数键值对】
- 3、【第一次】发送网络请求,获取验证码图片的网络字节流
- 4、将得到的验证码图片的网络字节流,写入到本地图片文件
- 5、手动打开写入本地的验证码图片
- 6、程序读取输入查看到的验证码,作为后续网络请求的参数
- 7、将输入的验证码,作为【请求头参数键值对】
- 8、【第二次】发送网络请求,获取后台数据
- 9、整个过程使用 requests.Session() 机制保存登陆状态