python spider 应用

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() 机制保存登陆状态

你可能感兴趣的:(python spider 应用)