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