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('<div\sclass="f18 mb20">(.*?)</div>', 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("<p>","").replace("</p>", "").replace("<br>", "")
      #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" : "123636274@qq.com",
    "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() 机制保存登陆状态
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,175评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,674评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,151评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,597评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,505评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,969评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,455评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,118评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,227评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,213评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,214评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,928评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,512评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,616评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,848评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,228评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,772评论 2 339

推荐阅读更多精彩内容