爬虫—暴力查询快递100

平时我们都会用查询快递都会用到 快递100
今天试了一下用requests模拟该网站ajax请求查询物流信息,发现概率性的返回不了结果,但是网站里手动查询却是ok的,so what?我也不知道咋回事。干脆换个暴力点的方法,selenium,优点:完全模仿浏览器操作,所见即可爬(音频文件除外),缺点:稍微有点慢。直接上代码

1、构建browser对象
此处选择 PhantomJS 无界面浏览器,虽然selenium官方已经打算放弃该浏览器了,但是目前还能用,个人觉得很好用。

先构建一个PhantomJS的浏览器对象,再设置一个显式等待

class A():

    # 构建browser对象
    _url="https://www.kuaidi100.com/"
    browser = selenium.webdriver.PhantomJS()
    wait = WebDriverWait(browser, 10)                          # 设置显式等待
    browser.get(_url)

2、模拟浏览器端快递查询,获取查询到的网页源码

网页端

   @classmethod
   def get_page_source(cls, code):
       """
       获取快递查询页网页源码
       :param code:
       :return: 网页源码或者False
       """
       try:
           # 获取快递单号输入框
           input = cls.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "#postid")))
           # 获取查询按钮
           s = cls.wait.until(ec.element_to_be_clickable((By.CSS_SELECTOR, "#query")))
           # 先清空快递单号输入框,在输入快递单号
           input.clear()
           input.send_keys(code)
           # 点击查询
           s.click()
           time.sleep(1)
           # 是否查询到物流信息,查询成功返回网页源码,并关闭浏览器,腾出资源
           try:
               # 预查询数据,查看窗口元素
               cls.browser.find_element_by_css_selector("table.result-info")
               result_flag = True
           except:
               result_flag = False
           if result_flag:
               html = cls.browser.page_source
               cls.browser.close()
               return html
           # 未查询到记录
           no_find = cls.browser.find_element_by_id("notFindTip")
           if no_find:
               print("暂无查询记录")
               return False
           # 查询时发生错误
           error_message=cls.browser.find_element_by_id("errorMessage")
           if error_message:
               print(error_message.text)
               return False
           return False
       
       # 捕获一些异常,避免程序崩掉
       except Exception as e:
           print("error: ", e)
           return False

3、解析网页源码,获取目标数据

    @classmethod
    def parse_page_source(cls, html):
        # 用pyquery解析网页源码
        pq=pyquery.PyQuery(html)
        # 获取物流信息网页元素
        items = pq("#queryResult > div.result-wrap > div.relative.query-box > table > tbody > tr")
        # 依次迭代获取到的物流信息网页元素
        for i in items.items():
            # 获取时间信息
            t = i("td.row1").text()
            # 将星期数标准化
            weekend=cls.generate_weekend(t[0:10])
            # 将时间格式标准化
            t = t[0:10] + '\t' + t[10:15] + '\t' + weekend
            # 获取物流状态
            status = i("td:last-child").text()
            print(t.ljust(25), status.ljust(1))

    @classmethod
    def generate_weekend(cls, date_str):
        list = ['一', '二', '三', '四', '五', '六', '日']
        weekend = datetime.datetime.strptime(date_str, "%Y.%m.%d").isoweekday()
        weekend = "星期" + dict(enumerate(list, 1)).get(weekend)
        return weekend

4、将相关函数进行封装

以下是整个程序源代码以及运行结果

import time
import pyquery
import datetime
import selenium.webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec


class A():
    # 构建browser对象
    _url = "https://www.kuaidi100.com/"
    browser = selenium.webdriver.PhantomJS()
    wait = WebDriverWait(browser, 10)
    browser.get(_url)

    @classmethod
    def do(cls):
        code = input("输入快递单号: ")
        ret = cls.get_page_source(code)
        if not ret:
            return ret
        cls.parse_page_source(ret)

    @classmethod
    def get_page_source(cls, code):
        """
        获取快递查询页网页源码
        :param code:
        :return: 网页源码或者False
        """
        try:
            # 获取快递单号输入框
            input = cls.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "#postid")))
            # 获取查询按钮
            s = cls.wait.until(ec.element_to_be_clickable((By.CSS_SELECTOR, "#query")))
            # 先清空快递单号输入框,在输入快递单号
            input.clear()
            input.send_keys(code)
            # 点击查询
            s.click()
            time.sleep(1)
            # 是否查询到物流信息,查询成功返回网页源码,并关闭浏览器,腾出资源
           try:
                # 预查询数据,查看窗口元素
                cls.browser.find_element_by_css_selector("table.result-info")
                result_flag = True
            except:
                result_flag = False
            if result_flag:
                html = cls.browser.page_source
                cls.browser.close()
                return html
            # 未查询到记录
            no_find = cls.browser.find_element_by_id("notFindTip")
            if no_find:
                print("暂无查询记录")
                return False
            # 查询时发生错误
            error_message = cls.browser.find_element_by_id("errorMessage")
            if error_message:
                print(error_message.text)
                return False
            return False

        # 捕获一些异常,避免程序崩掉
        except Exception as e:
            print("error: ", e)
            return False

    @classmethod
    def parse_page_source(cls, html):
        # 用pyquery解析网页源码
        pq = pyquery.PyQuery(html)
        # 获取物流信息网页元素
        items = pq("#queryResult > div.result-wrap > div.relative.query-box > table > tbody > tr")
        # 依次迭代获取到的物流信息网页元素
        for i in items.items():
            # 获取时间信息
            t = i("td.row1").text()
            # 将星期数标准化
            weekend = cls.generate_weekend(t[0:10])
            # 将时间格式标准化
            t = t[0:10] + '\t' + t[10:15] + '\t' + weekend
            # 获取物流状态
            status = i("td:last-child").text()
            print(t.ljust(25), status.ljust(1))

    @classmethod
    def generate_weekend(cls, date_str):
        list = ['一', '二', '三', '四', '五', '六', '日']
        weekend = datetime.datetime.strptime(date_str, "%Y.%m.%d").isoweekday()
        weekend = "星期" + dict(enumerate(list, 1)).get(weekend)
        return weekend


if __name__ == "__main__":
    A.do()

>>>
输入快递单号: YT4031232184872
2019.08.18  15:16   星期日      客户 签收人: 已签收,签收人凭取货码签收。 已签收 感谢使用圆通速递,期待再次为您服务
2019.08.17  09:33   星期六      快件已暂存至西安糜家桥西门店菜鸟驿站,如有疑问请联系18502974450
2019.08.17  08:10   星期六      【陕西省西安市高科广场公司】 派件人: xxx 派件中 派件员电话18220687549
2019.08.17  07:52   星期六      【陕西省西安市高科广场公司】 已收入
2019.08.16  20:32   星期五      【西安转运中心】 已发出 下一站 【陕西省西安市高科广场公司】
2019.08.16  19:37   星期五      【西安转运中心】 已收入
2019.08.16  00:22   星期五      【成都转运中心】 已发出 下一站 【西安转运中心】
2019.08.16  00:08   星期五      【成都转运中心】 已收入
2019.08.14  20:52   星期三      【四川省直营市场部】 已发出 下一站 【成都转运中心】
2019.08.14  20:52   星期三      【四川省直营市场部公司】 已收件

Process finished with exit code 0
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351