python实现的一个火车票转让信息采集器


Posted in Python onJuly 09, 2014

好吧,我承认我是对晚上看到一张合适的票转让但打过电话去说已经被搞走了这件事情感到蛋疼。直接上文件吧。

#coding: utf-8
'''
春运查询火车票转让信息
Author: piglei2007@gmail.com
Date: 2011.01.25
'''
import re
import os
import time
import urlparse
import datetime
import traceback
import urllib2
import socket
socket.setdefaulttimeout(20)

BLANK_RE = re.compile(r"\s+")

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
opener.addheaders = [
  ("User-agent", "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.9.1) Gecko/20090704 Firefox/3.5"),
  ("Accept", "*/*"),
]
urllib2.install_opener(opener)

from BeautifulSoup import BeautifulSoup

SOURCE = {
  "58": "http://bj.58.com/huochepiao/?Num=%(train)s&StartTime=%(date)s00",
  "ganji": "http://bj.ganji.com/piao/cc_%(train)s/%(date)s/",
}
RECORD_FILE = "/tmp/ticket_records.txt"

def parse_record():
  try:
    return set([x.strip() for x in open(RECORD_FILE, "r").readlines()])
  except IOError:
    open(RECORD_FILE, "w")
    return set()

def flush_record(records):
  open(RECORD_FILE, "w").write("\n".join(records))

def main(config):
  """
  开始抓取
  """
  existed = parse_record()
  to_email = []

  for train in config["trains"]:
    for date in config["dates"]:
      for type, _url in SOURCE.items():
        url = _url % dict(train=train, date=date)
        content = urllib2.urlopen(url).read()
        soup = BeautifulSoup(content)
        result = parse_content(type, soup, train)
        for url, text in result:
          url = urlparse.urljoin(_url, url)
          # 只要卧铺!
          if url not in existed and u"卧" in text:
            to_email.append([text, url])
          existed.add(url)
  if to_email:
    content = "".join(
      [x for x in [" | ".join(y) for y in to_email]]
    ).encode("utf-8")
    simple_mail(config["people"], content)
  flush_record(existed)

def parse_content(type, soup, train):
  """
  获得车次信息
  """
  result = []
  if type == "58":
    info_table = soup.find("table", id="infolist")
    if info_table:
      for x in info_table.findAll("tr", text=re.compile(ur"%s(?!时刻表)" % train, re.I)):
        a = x.parent
        _text = BLANK_RE.sub("", a.text)
        result.append([a["href"], _text])
  if type == "ganji":
    for x in soup.findAll("dl", {"class": "list_piao"}):
      a = x.dt.a
      result.append([a["href"], a.text])
  return result

EMAIL_HOST = 'smtp.sohu.com'
EMAIL_HOST_USER = 'yourname@sohu.com'
EMAIL_HOST_PASSWORD = 'yourpassword'
EMAIL_PORT = 25

def simple_mail(to, content):
  """
  发送邮件
  """
  import smtplib
  from email.mime.text import MIMEText

  msgRoot = MIMEText(content, 'html', 'UTF-8')
  msgRoot['Subject'] = "[%s]有票来啦!!!!" % datetime.datetime.today().isoformat(" ")
  msgRoot['From'] = EMAIL_HOST_USER
  msgRoot['To'] = ", ".join(to)

  s = smtplib.SMTP(EMAIL_HOST, EMAIL_PORT)
  s.login(EMAIL_HOST_USER, EMAIL_HOST_PASSWORD)
  s.sendmail(EMAIL_HOST_USER, to, msgRoot.as_string())
  s.close()

def switch_time_zone():
  """
  切换时区
  """
  os.environ["TZ"] = "Asia/Shanghai"
  time.tzset()

switch_time_zone()

if __name__ == '__main__':
  config = {
    "trains": ("k471",),
    "dates": ("20110129",),
    "people": (
      "youremail@sohu.com",
    )
  }
  try:
    main(config)
    print "%s: ok" % datetime.datetime.today()
  except Exception, e:
    print traceback.format_exc()

然后放入cron,你懂的。

Python 相关文章推荐
初步讲解Python中的元组概念
May 21 Python
pandas 两列时间相减换算为秒的方法
Apr 20 Python
python使用openpyxl库修改excel表格数据方法
May 03 Python
Python实现通过继承覆盖方法示例
Jul 02 Python
python基础学习之如何对元组各个元素进行命名详解
Jul 12 Python
Python3.5 处理文本txt,删除不需要的行方法
Dec 10 Python
详解Python3之数据指纹MD5校验与对比
Jun 11 Python
python如何求数组连续最大和的示例代码
Feb 04 Python
python实现FTP循环上传文件
Mar 20 Python
python cookie反爬处理的实现
Nov 01 Python
基于python模拟TCP3次握手连接及发送数据
Nov 06 Python
使用Python实现NBA球员数据查询小程序功能
Nov 09 Python
python的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享
Jul 09 #Python
Python中__init__和__new__的区别详解
Jul 09 #Python
Python中使用logging模块代替print(logging简明指南)
Jul 09 #Python
Python中的魔法方法深入理解
Jul 09 #Python
gearman的安装启动及python API使用实例
Jul 08 #Python
python实现跨文件全局变量的方法
Jul 07 #Python
Python中的并发编程实例
Jul 07 #Python
You might like
PHP完整的日历类(CLASS)
2006/11/27 PHP
PHP文件注释标记及规范小结
2012/04/01 PHP
利用php递归实现无限分类 格式化数组的详解
2013/06/08 PHP
php中session使用示例
2014/03/29 PHP
关于WordPress的SEO优化相关的一些PHP页面脚本技巧
2015/12/10 PHP
JavaScript入门教程(3) js面向对象
2009/01/31 Javascript
基于jquery的自定义鼠标提示效果 jquery.toolTip
2010/11/14 Javascript
JavaScript 一道字符串分解的题目
2011/08/03 Javascript
jQuery性能优化28条建议你值得借鉴
2013/02/16 Javascript
JS如何将数字类型转化为没3个一个逗号的金钱格式
2014/01/27 Javascript
JavaScript控制table某列不显示的方法
2015/03/16 Javascript
JavaScript中split() 使用方法汇总
2015/04/17 Javascript
javascript实现控制div颜色
2015/07/07 Javascript
JS实现仿QQ效果的三级竖向菜单
2015/09/25 Javascript
jQuery向父辈遍历的简单方法
2016/09/18 Javascript
AngularJS自定义控件实例详解
2016/12/13 Javascript
JS实现队列的先进先出功能示例
2017/05/10 Javascript
原生JavaScript实现的简单省市县三级联动功能示例
2017/05/27 Javascript
Js中async/await的执行顺序详解
2017/09/22 Javascript
vue中Axios的封装与API接口的管理详解
2018/08/09 Javascript
详解Django的model查询操作与查询性能优化
2018/10/16 Python
Python中关于浮点数的冷知识
2019/09/22 Python
安装python及pycharm的教程图解
2019/10/10 Python
找Python安装目录,设置环境路径以及在命令行运行python脚本实例
2020/03/09 Python
Canvas 文本填充线性渐变的使用详解
2020/06/22 HTML / CSS
Hotter Shoes美国官网:英国最受欢迎的舒适鞋
2018/08/02 全球购物
描述一下JVM加载class文件的原理机制
2013/12/08 面试题
领导班子个人对照检查材料(群众路线)
2014/09/26 职场文书
2014年教师工作总结
2014/11/10 职场文书
2015年大学生社会实践评语
2015/03/26 职场文书
2015年七年级班主任工作总结
2015/05/21 职场文书
学生会招新宣传语
2015/07/13 职场文书
2016年清明节网上祭英烈活动总结
2016/04/01 职场文书
解决golang结构体tag编译错误的问题
2021/05/02 Golang
「SHOW BY ROCK!!」“雫シークレットマインド”组合单曲MV公开
2022/03/21 日漫
Java多线程并发FutureTask使用详解
2022/06/28 Java/Android