美文网首页
爬虫—暴力查询快递100

爬虫—暴力查询快递100

作者: 八戒无戒 | 来源:发表于2019-08-18 15:57 被阅读0次

    平时我们都会用查询快递都会用到 快递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
    

    相关文章

      网友评论

          本文标题:爬虫—暴力查询快递100

          本文链接:https://www.haomeiwen.com/subject/fjbrsctx.html